在mysql中使用union和order by子句

Adi*_*tya 118 mysql sql union sql-order-by

我想在mysql查询中使用union with order.我根据不同的标准从基于距离的表中获取不同类型的记录,以便在我的网站上进行搜索.第一个选择查询返回与确切位置搜索相关的数据.第二个选择查询返回与距离搜索位置5公里内的距离相关的数据.第三个选择查询返回与距搜索地点5-15公里范围内的距离相关的数据.

然后我使用union来合并所有结果并在页面上显示分页.在"精确搜索结果","5公里范围内的结果"等适当标题下

现在我想基于id或add_date对结果进行排序.但是当我在查询结束时添加order by子句时(query1 union query 2 union query 3 order by add_date).它排序所有结果.但我想要的是它应该在每个标题下排序.

Red*_*ter 211

您可以通过向每个选择添加一个名为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
Run Code Online (Sandbox Code Playgroud)

  • MySQL要求派生表具有别名. (24认同)
  • 为什么有'a`和结束? (9认同)
  • @RedFilter,我不太明白.当我们**可以简单地**选择所有3个表然后执行`order by`时,"选择所有作为派生表"的重点是什么?([*"对整个`UNION`结果进行排序或限制,将各个`SELECT`语句加上括号,并在最后一个之后放置`ORDER BY`或`LIMIT`"*](https://dev.mysql.com /doc/refman/5.7/en/union.html)).将您的代码与http://i.stack.imgur.com/LpTMU.png进行比较 (4认同)

ric*_*fox 41

您可以使用子查询执行此操作:

select * from (select values1 from table1 order by orderby1) as a
union all
select * from (select values2 from table2 order by orderby2) as b
Run Code Online (Sandbox Code Playgroud)

  • 这是[不正确](http://dev.mysql.com/doc/refman/5.7/en/union.html):*对`SELECT`语句使用`ORDER BY`意味着没有关于行出现在最终结果中* (18认同)
  • 这对于较早的MySQL版本非常有效,现在这种方法将无法使用。因为SQL标准不保证保留子查询的顺序。 (2认同)

小智 26

(select add_date,col2 from table_name) 
  union 
(select add_date,col2 from table_name) 
  union 
(select add_date,col2 from table_name) 

order by add_date
Run Code Online (Sandbox Code Playgroud)


hdi*_*fen 9

ORDER BY当您在与 mysql 结合使用的子查询中使用子句时UNION,将会优化掉该ORDER BY子句。

这是因为默认情况下 aUNION返回一个无序列表,因此 anORDER 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);
Run Code Online (Sandbox Code Playgroud)

但是,对各个 SELECT 语句使用 ORDER BY 并不意味着行在最终结果中出现的顺序,因为 UNION 默认情况下会生成无序的行集。因此,在此上下文中使用 ORDER BY 通常与 LIMIT 结合使用,以便它用于确定要为 SELECT 检索的选定行的子集,即使它不一定影响这些行在 SELECT 中的顺序。最终的 UNION 结果。如果 ORDER BY 在 SELECT 中出现但没有 LIMIT,则会被优化掉,因为无论如何它都不会产生任何效果。

最后一句话有点误导,因为它应该有效果。当您需要在子查询中进行排序时,此优化会导致问题。

要强制 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)
Run Code Online (Sandbox Code Playgroud)

LIMIT意味着OFFSET如果您想要执行分页之类的操作,您可以在整个查询中添加一个。

这还为您带来了额外的好处,即能够ORDER BY为每个联合使用不同的列。


use*_*841 8

联合查询只能有一个主ORDER BY子句IIRC.为了得到这一点,在每个查询组成更大的UNION查询,添加一个字段,将在是你的一个字段排序UNIONORDER 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
Run Code Online (Sandbox Code Playgroud)

union_sort字段可以是您可能想要排序的任何字段.在这个例子中,它恰好放在第一个表的第一个表,第二个表的第二个等的结果.


Ger*_*ill 8

不要忘记,union all是一种在没有排序或合并(而不是union)的情况下将记录添加到记录集的方法.

例如:

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
Run Code Online (Sandbox Code Playgroud)

它使各个查询更清晰,并允许您按每个查询中的不同参数进行排序.但是,通过使用所选答案的方式,它可能会变得更加清晰,具体取决于复杂性以及数据的相关性,因为您正在对排序进行概念化.它还允许您将人工列返回到查询程序,以便它具有可以排序或组织的上下文.

但是这种方式的优点是速度快,不会引入额外的变量,并且可以轻松地分离出包括排序在内的每个查询.添加限制的能力只是额外的奖励.

当然可以随意将union all转换为union,并为整个查询添加一个排序.或添加一个人工ID,在这种情况下,这种方式可以很容易地按每个查询中的不同参数进行排序,但它与接受的答案相同.