Приоритет ORDER BY над GROUP BY в MySQL без подзапроса - PullRequest
6 голосов
/ 17 января 2011

У меня есть следующий запрос, который делает то, что я хочу, но я подозреваю, что это можно сделать без подзапроса:

  SELECT * 
    FROM (SELECT * 
            FROM 'versions' 
        ORDER BY 'ID' DESC) AS X 
GROUP BY 'program'

Мне нужно сгруппировать по программе, но вернуть результаты дляобъекты в версиях с наибольшим значением "ID".

В моем прошлом опыте такой запрос должен работать в MySQL, но по некоторым причинам это не так:

  SELECT * 
    FROM 'versions' 
GROUP BY 'program' 
ORDER BY MAX('ID') DESC

Я хочу сделать так, чтобы MySQL сначала выполнял ORDER BY, а затем GROUP BY, но он настаивал на том, чтобы сначала GROUP BY, а затем ORDERОТ.то есть сортировка результатов группировки вместо группировки результатов упорядочения.

Конечно, невозможно написать

SELECT * FROM 'versions' ORDER BY 'ID' DESC GROUP BY 'program'

Спасибо.

Ответы [ 3 ]

3 голосов
/ 17 января 2011

По определению, ORDER BY обрабатывается после группировки с GROUP BY.По определению, концептуальный способ обработки любого оператора SELECT:

  1. Вычислить декартово произведение всех таблиц, на которые есть ссылки в предложении FROM
  2. Применить критерии объединения из предложения FROM для фильтрациирезультаты
  3. Примените критерии фильтрации в предложении WHERE для дальнейшей фильтрации результатов
  4. Сгруппируйте результаты в подмножества на основе предложения GROUP BY, свернув результаты в одну строку для каждого такого подмножества.и вычисление значений любых агрегатных функций - SUM(), MAX(), AVG() и т. д. - для каждого такого подмножества.Обратите внимание, что если предложение GROUP BY не указано, результаты обрабатываются так, как если бы существовало одно подмножество, а все агрегатные функции применяются ко всему набору результатов, сворачивая его в одну строку.
  5. Фильтровать сгруппированные сейчасрезультаты на основе предложения HAVING.
  6. Сортировка результатов на основе предложения ORDER BY.

Единственные столбцы, разрешенные в наборе результатов SELECT с предложением GROUP BY, это:конечно,

  • Столбцы, на которые есть ссылка в предложении GROUP BY
  • Агрегатные функции (например, MAX())
  • литерал / константы
  • выражения, полученные из любого из вышеперечисленного.

Только неработающие реализации SQL допускают такие вещи, как select xxx,yyy,a,b,c FROM foo GROUP BY xxx,yyy - ссылки на colulmsn a, b и c не имеют смысла / не определены, учитывая, что отдельные группы были свернутыв один ряд,

2 голосов
/ 17 января 2011

Это должно делать это и работать довольно хорошо, пока есть составной индекс (program, id). Подзапрос должен проверять только самый первый идентификатор для каждой ветви программы и быстро извлекать необходимую запись из внешнего запроса.

select v.*
from
(
    select program, MAX(id) id
    from versions
    group by program
) m
inner join versions v on m.program=v.program and m.id=v.id
2 голосов
/ 17 января 2011
SELECT  v.*
FROM    (
        SELECT  DISTINCT program
        FROM    versions
        ) vd
JOIN    versions v
ON      v.id = 
        (
        SELECT  vi.id
        FROM    versions vi
        WHERE   vi.program = vd.program
        ORDER BY
                vi.program DESC, vi.id DESC
        LIMIT 1
        )

Создайте индекс для (program, id), чтобы он работал быстро.

Относительно вашего исходного запроса:

SELECT * FROM 'versions' GROUP BY 'program' ORDER BY MAX('ID') DESC

Этот запрос не будет обрабатываться на любом диалекте SQL, кроме MySQL.

Он злоупотребляет способностью MySQL возвращать несгруппированные и неагрегированные выражения из оператора GROUP BY.

...