在mysql中使用union和order by子句

时间:2010-08-20 13:29:04

标签: mysql sql sql-order-by union

我想在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)。它排序所有结果。但我想要的是它应该在每个标题下排序。

11 个答案:

答案 0 :(得分:199)

您可以通过在每个选择中添加一个名为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

答案 1 :(得分: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

答案 2 :(得分:25)

(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

答案 3 :(得分:8)

别忘了,union all是一种将记录添加到记录集而无需排序或合并(而不是联合)的方法。

例如:

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

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

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

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

答案 4 :(得分:7)

联合查询只能有一个主ORDER BY子句IIRC。为此,在构成较大UNION查询的每个查询中,添加一个字段,该字段将是您为UNION的{​​{1}}排序的一个字段。

例如,您可能有类似

的内容
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 字段可以是您可能想要排序的任何内容。在这个例子中,它恰好放在第一个表的第一个表,第二个表的结果等等

答案 5 :(得分:4)

我得到了加入加联盟的工作。

(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

答案 6 :(得分:0)

尝试:

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

[QUERY 1]和[QUERY 2]是您要合并的两个查询。

答案 7 :(得分:0)

这是因为你要对整个结果集进行排序,你应该对联合的每个部分进行分类,或者你可以使用ORDER BY(Something ie .subsquery distance)THEN(东西即行id)子句

答案 8 :(得分:0)

我尝试在联合之前将订单添加到每个查询中,如

(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

这可能有点棘手,因为你想按范围分组,但我认为它应该是可行的。

答案 9 :(得分:0)

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

这是因为默认情况下,UNION返回无序列表,因此ORDER BY不会执行任何操作。

in the docs提到了优化,并说:

  

要将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);
     

但是,对单个SELECT语句使用ORDER BY意味着   行在最终结果中出现的顺序无关紧要   因为默认情况下UNION会生成无序的行集。因此,   在这种情况下,通常将ORDER BY与   LIMIT,以便用于确定所选行的子集   检索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)

LIMIT高意味着如果您想执行诸如分页之类的操作,则可以在整个查询上添加OFFSET

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

答案 10 :(得分:0)

仅按列号使用顺序(不使用列名)。 每个查询都会返回一些列,因此您可以使用其编号按任何所需的列进行排序。