SQL - использование псевдонима в группе By

Просто интересуется синтаксисом SQL. Поэтому, если у меня есть

SELECT 
 itemName as ItemName,
 substring(itemName, 1,1) as FirstLetter,
 Count(itemName)
FROM table1
GROUP BY itemName, FirstLetter

Это неверно, потому что

GROUP BY itemName, FirstLetter 

действительно должно быть

GROUP BY itemName, substring(itemName, 1,1)

Но почему мы не можем просто использовать первое для удобства?

Ответ 1

SQL реализуется так, как если бы запрос выполнялся в следующем порядке:

  • Предложение FROM
  • Предложение WHERE
  • Предложение GROUP BY
  • Предложение HAVING
  • Предложение SELECT
  • Предложение ORDER BY

Для большинства реляционных систем баз данных этот порядок объясняет, какие имена (столбцы или псевдонимы) действительны, поскольку они должны были быть введены на предыдущем шаге.

Итак, в Oracle и SQL Server вы не можете использовать термин в предложении GROUP BY, который вы определяете в предложении SELECT, потому что GROUP BY выполняется перед предложением SELECT.

Есть исключения: MySQL и Postgres, похоже, обладают дополнительным умением, которое позволяет это.

Ответ 2

Вы всегда можете использовать подзапрос, чтобы использовать псевдоним; Конечно, проверьте производительность (возможно, сервер db будет работать одинаково, но никогда не боится проверять):

SELECT ItemName, FirstLetter, COUNT(ItemName)
FROM (
    SELECT ItemName, SUBSTRING(ItemName, 1, 1) AS FirstLetter
    FROM table1
    ) ItemNames
GROUP BY ItemName, FirstLetter

Ответ 3

По крайней мере, в PostgreSQL вы можете использовать номер столбца в наборе результатов в своем предложении GROUP BY:

SELECT 
 itemName as ItemName,
 substring(itemName, 1,1) as FirstLetter,
 Count(itemName)
FROM table1
GROUP BY 1, 2

Конечно, это становится больно, если вы делаете это в интерактивном режиме, и вы редактируете запрос, чтобы изменить количество или порядок столбцов в результате. Но все равно.

Ответ 4

SQL Server не позволяет ссылаться на псевдоним в предложении GROUP BY из-за логического порядка обработки. Предложение GROUP BY обрабатывается перед предложением SELECT, поэтому псевдоним неизвестен, когда вычисляется предложение GROUP BY. Это также объясняет, почему вы можете использовать псевдоним в предложении ORDER BY.

Вот один из источников информации о этапах логической обработки SQL Server.

Ответ 5

Предостережение, что использование псевдонима в группе By (для служб, которые поддерживают его, например postgres), может иметь непреднамеренные результаты. Например, если вы создаете псевдоним, который уже существует во внутреннем выражении, Group By будет выбирать имя внутреннего поля.

-- Working example in postgres
select col1 as col1_1, avg(col3) as col2_1
from
    (select gender as col1, maritalstatus as col2, 
    yearlyincome as col3 from customer) as layer_1
group by col1_1;

-- Failing example in postgres
select col2 as col1, avg(col3)
from
    (select gender as col1, maritalstatus as col2,
    yearlyincome as col3 from customer) as layer_1
group by col1;

Ответ 6

Некоторые СУБД позволят вам использовать псевдоним вместо того, чтобы повторять все выражение.
Одним из таких примеров является Teradata.

Я избегаю обозначения порядковых позиций, рекомендованного Биллом по причинам, описанным в этом вопросе SO.

Легкая и надежная альтернатива - всегда повторять выражение в предложении GROUP BY.
DRY не применяется к SQL.

Ответ 7

Остерегайтесь использования псевдонимов при группировке результатов из представления в SQLite. Вы получите неожиданные результаты, если имя псевдонима совпадает с именем столбца всех базовых таблиц (к представлениям.)

Ответ 8

В тот же день я обнаружил, что Rdb, бывший продукт DEC, поддерживаемый Oracle, позволил использовать псевдоним столбца в GROUP BY. Mainstream Oracle через версию 11 не позволяет использовать псевдоним столбцов в GROUP BY. Не уверен, что Postgresql, SQL Server, MySQL и т.д. Будет или не позволит. YMMV.

Ответ 9

Я не отвечаю, почему это так, но только хотел показать способ ограничения этого ограничения в SQL Server, используя CROSS APPLY для создания псевдонима. Затем вы используете его в предложении GROUP BY, например:

SELECT 
 itemName as ItemName,
 FirstLetter,
 Count(itemName)
FROM table1
CROSS APPLY (SELECT substring(itemName, 1,1) as FirstLetter) Alias
GROUP BY itemName, FirstLetter