Запрос, требующий, чтобы столбцы в предложении «Order By» соответствовали столбцам в предложении «Group by» - PullRequest
3 голосов
/ 14 ноября 2011

Немного странный этот. Я пытаюсь выполнить следующий запрос, объединяющий 3 таблицы.

Select t3.id, t3.name, t3.phone_no, t1.reg_dtm, count(t1.reg_dtm)
from tableA t1, tableB t2, tableC t3
Where t1.id = t2.id
And t2.id = t3.id
Group by t3.id, t3.name, t3.phone_no, t1.reg_dtm
Order by t2.id, t1.reg_dtm

Приведенный выше запрос возвращает следующую ошибку

ORA-00979: not a GROUP BY expression

Но если я изменю его так, чтобы все в предложении group by находилось в порядке order by, то оно работает.

Select t3.id, t3.name, t3.phone_no, t1.reg_dtm, count(t1.reg_dtm)
from tableA t1, tableB t2, tableC t3
Where t1.id = t2.id
And t2.id = t3.id
Group by t3.id, t3.name, t3.phone_no, t1.reg_dtm
Order by t3.id, t3.name, t3.phone_no, t1.reg_dtm

Что именно является причиной этого?

Я думаю, что проблема, возможно, в том, что t2.id, показанный в операторе order by в первом запросе, не является частью оператора group by. Если это причина, то почему это важно? Я никогда не сталкивался с этим раньше и не думал, что существует какая-либо связь между группой и порядком по заявлениям.

Я проверял вышеизложенное как на Oracle 10G, так и на MySQL.

Заранее спасибо

Ответы [ 5 ]

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

Столбцы, которые технически не упомянуты в предложении GROUP BY, не должны быть в наборе результатов (если они не агрегированы, т. Е. max(columnname)) - так как же имеет смысл ORDER BY их?Другими словами, что бы вообще означал такой запрос?

Однако MySQL (я не знаю о других) позволяет выбирать столбцы, которых нет в GROUP BY, что приводит к путаницедля начинающих, задающихся вопросом, почему они получают странные результаты запроса.

В качестве sidenote вы можете избегать неявных объединений, как обсуждено здесь .

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

Предложение ORDER BY выполняется после выполнения всего остального в операторе SELECT;в сценарии группирования набор результатов ограничен столбцами, используемыми для агрегирования данных.Если в исходном наборе результатов не указан столбец, обработчик не поймет, что делать с запрошенным выводом.

Другими словами, поскольку ваш запрос не возвращает различные значения для t2.id и t1.id (так как они не используются в предложении GROUP BY), движок не может вернуть данные в таком порядке.

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

Как правило, вы не можете упорядочить по столбцам, которых нет в предложении GROUP BY и которые не являются агрегатными функциями в списке SELECT, поскольку база данных не имеет возможности детерминированной сортировки результатов. База данных обычно не знает, как такой столбец будет агрегирован в конечных результатах, поэтому она не знает, как обрабатывать случай, когда одна строка в результате является, например, результатом агрегирования строк в базовой таблице с значения 1 и 4, а другая строка в результате - это результат агрегирования строк в базовой таблице со значениями 2 и 3. Любой способ сортировки результатов можно считать неверным.

Теперь, в этом конкретном случае, поскольку вы выполняете внутренние объединения на ID между всеми тремя таблицами, база данных, теоретически, может быть достаточно умной, чтобы признать, что ORDER BY t2.id, t1.id семантически эквивалентен ORDER BY t3.id, t3.id, что можно оценить детерминистически. Однако я не знаю ни одной базы данных, которая бы встроила такой вид преобразования запросов в свой оптимизатор. И компромисс между потенциальными ошибками, возникающими, когда такой анализ идет не так, как правило, будет противоречить его включению, когда запросы, которые вы пытаетесь выполнить, не имеют большого логического смысла с точки зрения теории множеств.

1 голос
/ 14 ноября 2011

На самом деле, если вы внимательно читаете SQL, в первом операторе вы группируете по T3.ID, но сортируете по T2.ID.

Если это настоящий SQL, который вы используете, то вашпроблема в том, что у вас есть опечатка.

1 голос
/ 14 ноября 2011

Вы можете упорядочить только по столбцам, которые есть в предложении select - поэтому order by t3.ud, t1.reg_dtm должен сделать это и иметь ту же семантику.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...