Какой оператор в SQL переворачивает вертикальные столбцы в горизонтальные
Что проверяют
Знаете ли вы, что такое pivot (превращение значений строк в столбцы) и что стандартного оператора для этого нет. Ответ «PIVOT» верен только наполовину, поэтому следом почти всегда спрашивают, как сделать то же самое в PostgreSQL или MySQL.
Как отвечать
Назовите оператор и сразу его границы:
PIVOT: есть в SQL Server и Oracle. Он сам агрегирует: пишетеPIVOT (SUM(amount) FOR month IN (...)), и значения колонкиmonthстановятся заголовками столбцов. Обратная операцияUNPIVOTразворачивает столбцы обратно в строки;- условная агрегация: переносимый способ, работает в любой базе.
SUM(CASE WHEN month = 'jan' THEN amount END) AS janна каждое нужное значение плюсGROUP BY product. В PostgreSQL то же самое короче:SUM(amount) FILTER (WHERE month = 'jan'); crosstab: функция из расширенияtablefuncв PostgreSQL. Требует явно описать типы выходных колонок и отсортированный входной запрос, поэтому на практике чаще выбираютFILTER.
Ограничение общее для всех вариантов: набор столбцов фиксируется при написании запроса. Если месяцы или категории заранее неизвестны, остаётся динамический SQL (собрать текст запроса и выполнить) или разворот на стороне приложения.
Для Java-разработчика стоит добавить, что второй путь часто проще и безопаснее. Выбираете плоские строки product, month, amount, а в коде собираете Map<String, Map<String, BigDecimal>> через Collectors.groupingBy. Динамический SQL с подставленными в текст именами столбцов открывает дорогу инъекциям, а JPQL такого синтаксиса не знает, так что PIVOT всё равно пришлось бы писать нативным запросом.
Где спотыкаются
Выдают PIVOT за стандартный SQL. На вопросе «а в PostgreSQL?» ответ рассыпается, хотя условная агрегация решает задачу везде.
Не понимают, что PIVOT агрегирует сам. Если на одну пару «продукт, месяц» приходится несколько строк, значения сложатся или усреднятся в зависимости от выбранной функции, и об этом надо помнить.
Путают pivot с транспонированием всей таблицы. Оператор превращает значения одной колонки в заголовки, а не меняет строки и столбцы местами целиком.