Использование предложения union и order by в mysql

Я хочу использовать заказ с объединением в запросе mysql. Я получаю разные типы записей на основе разных критериев из таблицы на основе расстояния для поиска на моем сайте. Первый запрос выбора возвращает данные, относящиеся к точному поиску места. Второй запрос выбора возвращает данные, относящиеся к расстоянию в пределах 5 км от места поиска. Третий запрос выбора возвращает данные, относящиеся к расстоянию в пределах 5-15 км от места поиска.

Затем я использую объединение, чтобы объединить все результаты и показать на странице с разбиением на страницы. Под соответствующим заголовком "Точные результаты поиска", "Результаты в пределах 5 км" и т. Д.

Теперь я хочу отсортировать результаты по идентификатору или add_date. Но когда я добавляю предложение order by в конце моего запроса (query1 union query 2 union query 3 order by add_date). Он сортирует все результаты. Но я хочу, чтобы он сортировался по каждому заголовку.


person Aditya    schedule 20.08.2010    source источник
comment
По какому типу поля вы хотите сортировать в каждой таблице?   -  person user151841    schedule 20.08.2010


Ответы (11)


Вы можете сделать это, добавив псевдостолбец с именем rank к каждому выбору, который вы можете сначала отсортировать, а затем отсортировать по другим критериям, например:

select *
from (
    select 1 as Rank, id, add_date from Table 
    union all
    select 2 as Rank, id, add_date from Table where distance < 5
    union all
    select 3 as Rank, id, add_date from Table where distance between 5 and 15
) a
order by rank, id, add_date desc
person D'Arcy Rittich    schedule 20.08.2010
comment
Привет, спасибо за это, я именно так и использую. Но я хочу отсортировать результат выборочного запроса на основе add_date в порядке убывания. - person Aditya; 20.08.2010
comment
Вы можете использовать для этого ключевое слово desc. Я обновил запрос выше. - person D'Arcy Rittich; 20.08.2010
comment
Я просто быстро изменил коды, и результаты были потрясающими. Вы сделали мой день. Спасибо - person Aditya; 21.08.2010
comment
Почему есть a и конец? - person Uday Hiwarale; 23.12.2013
comment
MySQL требует, чтобы производные таблицы имели псевдоним. - person D'Arcy Rittich; 24.12.2013
comment
@RedFilter, я не совсем понимаю. В чем весь смысл выбора всех как производной таблицы, когда мы можем просто выбрать все 3 таблицы, а затем выполнить order by? (для сортировки или ограничения всего UNION результата, заключите в скобки отдельные SELECT и поместите ORDER BY или LIMIT после последнего). Сравните свой код с i.stack.imgur.com/LpTMU.png - person Pacerier; 05.05.2015
comment
@Pacerier Если этот синтаксис работает с MySQL, дерзайте! Мой синтаксис немного более кроссплатформенный, я обычно не работаю с MySQL. Я на самом деле предпочитаю его, поскольку он работает в более общих случаях, например, подумайте, когда вам нужны только первые десять совпадений из последнего запроса UNION - я думаю, вам все равно придется вернуться к моему синтаксису. - person D'Arcy Rittich; 06.05.2015
comment
@RedFilter, да этот синтаксис работает даже в MySQL 4.1. - person Pacerier; 25.05.2015
comment
@Pacerier, также учтите, что значение таким образом позволяет этому top select * вместо этого быть select id, add_date и убирать ранг из результатов, если вы не хотите их видеть. - person Dev Null; 30.09.2015
comment
@DevNull, да, это один допустимый вариант использования. - person Pacerier; 01.10.2015
comment
Подзапрос не требуется в MySQL - по крайней мере, в любой последней версии. - person Gordon Linoff; 24.10.2019
comment
Напоминание, выдержка из документации: UNION может иметь глобальные предложения ORDER BY и LIMIT, которые влияют на весь набор результатов. Если столбцы, полученные отдельными операторами SELECT, имеют псевдоним (AS), ORDER BY должен использовать этот псевдоним, а не настоящие имена столбцов. - person Fabien Haddadi; 08.10.2020

Для этого можно использовать подзапросы:

select * from (select values1 from table1 order by orderby1) as a
union all
select * from (select values2 from table2 order by orderby2) as b
person rickythefox    schedule 20.08.2010
comment
Tnx, Хороший для разделения заказов. Также у нас может быть другое расположение, если предложение порядка было обычным, но мы хотим, чтобы результаты были разделены (вместо разделения заказов): SELECT * FROM ( SELECT aaa AS Col, 1 AS Official FROM table1 UNION ALL SELECT bbb AS Col, 0 AS Official FROM table2 ) AS tbl ORDER BY Official, Col - person Alix; 12.12.2013
comment
Это неверно: использование ORDER BY для отдельных SELECT утверждения ничего не говорят о порядке, в котором строки появляются в конечном результате - person shmosel; 22.03.2016
comment
Вы правы, принятый ответ тоже правильный. Просто так получилось, что когда я это протестировал, это сработало. - person rickythefox; 29.03.2016
comment
shmosel (и rickythefox) - union all не удаляет дубликаты, и поэтому у него нет причин изменять вид ваших отдельных отсортированных выборок. Вот почему это сработало для вас в прошлом и почему оно будет работать для вас в будущем. Неправильный порядок в конечном результате связан с тем, что UNION (DISTINCT) требует какой-то сортировки для эффективного объединения строк. Или, более конкретно, сортирует, потому что эффективно объединяет строки. Таким образом, вы можете положиться на union all, чтобы сохранить свои подзапросы. - person Gerard ONeill; 22.08.2017
comment
Это отлично работало для более старых версий MySQL, теперь этот подход НЕ работает. Потому что стандарт SQL не гарантирует сохранения порядка подзапросов. - person Andrei; 18.06.2018

Не забывайте, что объединение всех - это способ добавления записей в набор записей без сортировки или слияния (в отличие от объединения).

Так например:

select * from (
    select col1, col2
    from table a
    <....>
    order by col3
    limit by 200
) a
union all
select * from (
    select cola, colb
    from table b
    <....>
    order by colb
    limit by 300
) b

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

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

И, конечно, не стесняйтесь превращать объединение в объединение и добавлять сортировку для всего запроса. Или добавьте искусственный идентификатор, и в этом случае этот способ упрощает сортировку по различным параметрам в каждом запросе, но в остальном он совпадает с принятым ответом.

person Gerard ONeill    schedule 29.09.2015

Запрос на объединение может иметь только одно главное предложение ORDER BY, IIRC. Чтобы получить это, в каждый запрос, составляющий больший UNION запрос, добавьте поле, которое будет единственным полем, по которому вы будете сортировать для UNION ORDER BY.

Например, у вас может быть что-то вроде

SELECT field1, field2, '1' AS union_sort
UNION SELECT field1, field2, '2' AS union_sort
UNION SELECT field1, field2, '3' AS union_sort
ORDER BY union_sort

Это поле union_sort может быть чем угодно, по вашему желанию. В этом примере просто случайно помещаются результаты из первой таблицы в первую, во вторую - из второй и т. Д.

person user151841    schedule 20.08.2010

Я получил это, работая над объединением плюс профсоюз.

(SELECT 
   table1.column1,
   table1.column2,
   foo1.column4
 FROM table1, table2, foo1, table5
 WHERE table5.somerecord = table1.column1
 ORDER BY table1.column1 ASC, table1.column2 DESC
)

UNION

(SELECT
    ... Another complex query as above
)

ORDER BY column1 DESC, column2 ASC
person Robert Saylor    schedule 10.06.2011

Когда вы используете предложение ORDER BY внутри подзапроса, используемого вместе с UNION, mysql оптимизирует предложение ORDER BY.

Это потому, что по умолчанию UNION возвращает неупорядоченный список, поэтому ORDER BY ничего не сделает.

Оптимизация упоминается в документации и гласит:

Чтобы применить ORDER BY или LIMIT к отдельному SELECT, поместите предложение в круглые скобки, которые заключают SELECT:

(SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10) UNION
(SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10);

Однако использование ORDER BY для отдельных операторов SELECT ничего не говорит о порядке, в котором строки появляются в конечном результате, поскольку UNION по умолчанию создает неупорядоченный набор строк. Поэтому использование ORDER BY в этом контексте обычно связано с LIMIT, так что он используется для определения подмножества выбранных строк для извлечения для SELECT, даже если это не обязательно влияет на порядок этих строк в окончательный результат UNION. Если ORDER BY появляется без LIMIT в SELECT, он оптимизируется, потому что в любом случае это не будет иметь никакого эффекта.

Последнее предложение немного вводит в заблуждение, потому что оно должно иметь эффект. Эта оптимизация вызывает проблему, когда вы находитесь в ситуации, когда вам нужно сделать заказ в подзапросе.

Чтобы заставить MySQL не выполнять эту оптимизацию, вы можете добавить предложение LIMIT, например:

(SELECT 1 AS rank, id, add_date FROM my_table WHERE distance < 5 ORDER BY add_date LIMIT 9999999999)
UNION ALL
(SELECT 2 AS rank, id, add_date FROM my_table WHERE distance BETWEEN 5 AND 15 ORDER BY rank LIMIT 9999999999)
UNION ALL
(SELECT 3 AS rank, id, add_date from my_table WHERE distance BETWEEN 5 and 15 ORDER BY id LIMIT 9999999999)

Высокий LIMIT означает, что вы можете добавить OFFSET к общему запросу, если хотите сделать что-то вроде разбивки на страницы.

Это также дает вам дополнительное преимущество, заключающееся в возможности ORDER BY разных столбцов для каждого объединения.

person hdifen    schedule 11.07.2019

Пытаться:

SELECT result.* 
FROM (
 [QUERY 1]
 UNION
 [QUERY 2]
) result
ORDER BY result.id

Где [QUERY 1] и [QUERY 2] - это два ваших запроса, которые вы хотите объединить.

person André Hoffmann    schedule 20.08.2010

Я попытался добавить порядок по каждому из запросов до объединения, например

(select * from table where distance=0 order by add_date) 
union 
(select * from table where distance>0 and distance<=5 order by add_date)

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

Я думаю, вам нужно будет сохранить порядок снаружи и добавить столбцы в предложении where к порядку, что-то вроде

(select * from table where distance=0) 
union 
(select * from table where distance>0 and distance<=5) 
order by distance, add_date

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

person Mike C    schedule 20.08.2010
comment
user151841 идея union_sort ниже была бы хорошим способом справиться с группировкой - person Mike C; 20.08.2010

Это связано с тем, что вы сортируете весь набор результатов, вы должны сортировать каждую часть объединения отдельно или вы можете использовать предложение ORDER BY (что-то, например, расстояние подзапроса) THEN (что-то, например идентификатор строки)

person canni    schedule 20.08.2010

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

person Nikhil Gupta    schedule 20.10.2020

person    schedule
comment
Это сработало, но, как ни странно, мне нужно было изменить одну вещь: мне нужно было дать общий псевдоним для поля, которое упорядочивало. Кроме того, работало, спасибо! - person HoldOffHunger; 14.09.2016