Запрос SELECT UNION SELECT с независимой сортировкой ORDER BY? - PullRequest
0 голосов
/ 24 декабря 2018

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

Базовая структура:

(SELECT * FROM table ORDER BY table.field DESC, table.timestamp DESC)
UNION ALL
(SELECT * FROM table ORDER BY table.timestamp DESC)

Я опускаю WHERE предложения, которые заставляют эти запросы возвращать совершенно разные результаты, но в той же форме.Проблема в том, что я ничего не добавляю к ORDER BY, это изменит его сортировку, и она не сортируется правильно.Фактически обе группы, кажется, сортируют назад.Но даже если я попытаюсь отсортировать по несвязанному числовому полю, порядок не изменится.

Может быть, UNION не то, что я хочу здесь?Есть ли «тупой» способ смешать два результата SQL вместе?

Я НЕ хочу, чтобы весь объединенный набор результатов имел одинаковую сортировку.Я пытаюсь получить список с особыми / важными элементами вверху, а затем с другими элементами в определенные временные рамки, показанные ниже, отсортированные по дате / времени.

Ответы [ 5 ]

0 голосов
/ 25 декабря 2018

Внутренний порядок не влияет на результат.Вы должны использовать Order Out Of union.

SELECT * From (
SELECT * FROM table
UNION ALL
SELECT * FROM table
) as T Order by T.field  DESC ,table.timestamp DESC
0 голосов
/ 24 декабря 2018

«Почему» : подзапрос по определению возвращает неупорядоченный набор строк.Оптимизатор только недавно начал использовать этот пункт в Стандарте.При этом он отбрасывает ORDER BY (если не существует LIMIT; см. План A).Порядок, который вы видели, был просто совпадением, основанным, возможно, на индексе, который использовался для удовлетворения WHERE.Чтобы правильно отсортировать результаты, вы должны применить некоторое упорядочение после этого (см. Планы B).

Другая недавняя оптимизация ... Ранее UNION всегда подавал результаты из каждого подзапроса ввременная таблица.Теперь, в случае UNION ALL (и некоторых других ограничений), он может передавать результаты непосредственно клиенту.(Тем не менее, мои предложенные планы B и C по-прежнему нуждаются в временном интервале для выполнения ORDER BY.)

План A - это помеха, которую может сработать:

(SELECT * FROM table ORDER BY table.field DESC, table.timestamp DESC
                     LIMIT 9999999)
UNION ALL
(SELECT * FROM table ORDER BY table.timestamp DESC
                     LIMIT 9999999)

План B может работать в зависимости от того, может ли ORDER BY соответствовать данным:

(SELECT * FROM table)
UNION ALL
(SELECT * FROM table)
ORDER BY table.field DESC, table.timestamp DESC

План C является попыткой обобщить План B:

(SELECT *, 1 AS seq1, table.field AS seq2 FROM table)
UNION ALL
(SELECT *, 2 AS seq1, 0 AS seq2 FROM table)
ORDER BY seq1,           -- to get the first SELECT first
         seq2 DESC,      -- unclear what your intent was with table.field
         timestamp DESC

Итог .Чтобы получить заказ, вы должны явно указать ORDER BY.(В настоящее время вы зависите от UNION работ, выполняемых последовательно. Некоторые день, UNIONs могут выполняться параллельно.)

0 голосов
/ 24 декабря 2018

Если я правильно понимаю, вы можете попытаться сделать столбец grp в подзапросе, чтобы представить два результата order by order.

SELECT t1.*
FROM (
    SELECT *,1 grp 
    FROM table 
    ORDER BY 
    UNION ALL
    SELECT *,2 
    FROM table 
) t1
ORDER BY t1.grp,t1.field DESC, t1.timestamp DESC
0 голосов
/ 24 декабря 2018

Включите условия where в order by.Как то так:

select t.*
from t
where (<1>) or (<2>)
order by (<1>) desc,  -- put the "1" rows first
         (case when <1> then t.field desc end),
         t.timestamp asc;
0 голосов
/ 24 декабря 2018

Я знаю, что это некрасиво, но попробуйте:

select a.* from (
(SELECT * FROM table ORDER BY table.field DESC, table.timestamp DESC)
) a
UNION ALL
select b.* from (
(SELECT * FROM table ORDER BY table.timestamp DESC)
) b

Примечание. Полагаю, вы знаете, что с Union

вы получите повторяющиеся результаты
...