Группировка данных в SQL Server иногда может стать сложной, особенно при работе с столбцами группировки, которые включают сложные выражения. В таких случаях логический порядок обработки запроса зачастую заставляет вас повторять выражение, так как его псевдоним не может быть использован в операторе GROUP BY. Однако существует решение, которое может упростить и улучшить читаемость ваших запросов GROUP BY.
Недавно Oracle представила мощный синтаксис в своем релизе 23c, позволяющий использовать псевдонимы столбцов в операторе GROUP BY. Эта функция значительно упрощает синтаксис и повышает общую читаемость запроса. Как пользователи SQL Server, мы можем только надеяться, что эта функциональность будет принята в будущих версиях SQL Server.
В настоящее время в SQL Server, когда вы пытаетесь использовать псевдоним, определенный в списке SELECT, в операторе GROUP BY, вы столкнетесь с ошибкой. Например:
SELECT TheMonth = DATEFROMPARTS(YEAR(create_date), MONTH(create_date), 1),
MonthlyDBs = COUNT(*)
FROM sys.databases
GROUP BY TheMonth;
Этот запрос приведет к следующей ошибке:
Msg 207, Level 16, State 1
Invalid column name 'TheMonth'.
Чтобы сгруппировать по столбцу ‘TheMonth’, вам необходимо использовать одно из следующих обходных решений:
- Повторение выражения:
- Использование общего выражения таблицы (CTE):
- Использование подзапроса:
- Использование CROSS APPLY:
SELECT TheMonth = DATEFROMPARTS(YEAR(create_date), MONTH(create_date), 1),
MonthlyDBs = COUNT(*)
FROM sys.databases
GROUP BY DATEFROMPARTS(YEAR(create_date), MONTH(create_date), 1);
WITH cte(TheMonth) AS
(
SELECT DATEFROMPARTS(YEAR(create_date), MONTH(create_date), 1)
FROM sys.databases
)
SELECT TheMonth, MonthlyDBs = COUNT(*)
FROM cte
GROUP BY TheMonth;
SELECT TheMonth, MonthlyDBs = COUNT(*)
FROM
(
SELECT DATEFROMPARTS(YEAR(create_date), MONTH(create_date), 1)
FROM sys.databases
) AS sq(TheMonth)
GROUP BY TheMonth;
SELECT TheMonth, MonthlyDBs = COUNT(*)
FROM sys.databases
CROSS APPLY
(
SELECT DATEFROMPARTS(YEAR(create_date), MONTH(create_date), 1)
) AS ca(TheMonth)
GROUP BY TheMonth;
Стоит отметить, что в SQL Server 2022 или Azure SQL Database вы можете упростить выражение, используя DATETRUNC(MONTH, create_date). Однако вы все равно не можете обойтись без использования одного из вышеуказанных обходных решений.
В Oracle, начиная с 23c, вы можете просто использовать следующий синтаксис:
SELECT TRUNC(DateTimeColumnName, 'MONTH') AS TheMonth,
COUNT(*) AS MonthlyWhatever
FROM TableName
GROUP BY TheMonth;
Эта форма намного удобнее и устраняет необходимость понимать логический порядок обработки. Она также разъясняет часто путающий факт о том, что псевдонимы из SELECT доступны в ORDER BY. Не было бы здорово иметь поддержку такого синтаксиса в SQL Server?
Однако важно учитывать, что слепое следование примеру Oracle не всегда является лучшим подходом. Например, недавнее добавление Oracle возможности GROUP BY column_position, которая позволяет ссылаться на группирующий столбец по его порядковому номеру, некоторыми рассматривается как бомба замедленного действия. Поэтому важно тщательно оценивать и внедрять новые функции в SQL Server.
В заключение, хотя SQL Server в настоящее время не имеет возможности использовать псевдонимы столбцов в операторе GROUP BY, существуют обходные решения, позволяющие достичь желаемых результатов. Было бы полезно для SQL Server принять синтаксис, представленный Oracle, так как он упрощает и повышает читаемость запросов GROUP BY. Однако важно подходить к новым функциям с осторожностью и учитывать их потенциальные последствия.
Дата последнего обновления статьи: 2023-12-01