Выбрать и сгруппировать вместе - PullRequest
5 голосов
/ 14 ноября 2011

У меня такой запрос:

Select 
  a.abc,
  a.cde,
  a.efg,
  a.agh,
  c.dummy
  p.test
  max(b.this)
  sum(b.sugar)
  sum(b.bucket)
  sum(b.something)

с последующим внешним соединением и внутренним соединением. Теперь проблема в том, когда в группе по

group by 
  a.abc,
  a.cde,
  a.efg,
  a.agh,
  c.dummy,
  p.test   

Запрос работает нормально. Но если я удаляю любого из них из группы, это дает:

SQLSTATE: 42803

Может кто-нибудь объяснить причину этой ошибки?

Ответы [ 2 ]

12 голосов
/ 14 ноября 2011

Как правило, любой столбец, который не входит в раздел group by, может быть включен в раздел select, только если к нему применена функция агрегирования. Или, по-другому, любые неагрегированные данные в разделе select должны быть сгруппированы.

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

LastName  FirstName  Salary
--------  ---------  ------
Smith     John       123456
Smith     George     111111
Diablo    Pax        999999

С запросом select LastName, Salary from Employees group by LastName вы ожидаете увидеть:

LastName  Salary
--------  ------
Smith     ??????
Diablo    999999

Заработная плата Смитов неисчислима, поскольку вы не знаете, какую функцию применять к ней, что и является причиной этой ошибки. Другими словами, СУБД не знает, что делать с 123456 и 111111, чтобы получить одно значение для сгруппированной строки.

Если вместо этого вы используете select LastName, sum(Salary) from Employees group by LastName (или max(), или min(), или ave(), или любую другую функцию агрегирования), СУБД будет знать, что делать. Для sum() он просто добавит их и даст вам 234567.

В вашем запросе эквивалент попытки использовать Salary без функции агрегирования состоит в том, чтобы изменить sum(b.this) на b.this, но не включать его в раздел group by. Или же удалите один из столбцов group by, не изменяя его на агрегацию в разделе select.

В обоих случаях у вас будет одна строка с кратными возможными значениями для столбца.

Документы DB2 на publib для sqlstate 42803 описывают вашу проблему:

Недопустимая ссылка на столбец в предложении SELECT или HAVING, поскольку он не является столбцом группировки; или ссылка на столбец в предложении GROUP BY недопустима.

2 голосов
/ 14 ноября 2011

SQL будет настаивать на том, что любой столбец в разделе SELECT либо включен в раздел GROUP BY, либо к нему применена агрегатная функция в разделе SELECT.

Эта статья дает хорошее объяснение, почему это так. Эта статья относится к SQL Server, но принцип должен быть примерно одинаковым для всех СУБД

...