UNION ALL和ORDER BY同时进行

时间:2013-12-18 22:53:18

标签: mysql sql

我有这个查询不起作用,我不明白为什么 每个SELECT语句都应返回降序结果,但它们是按升序排序的。 为什么?

(SELECT * FROM table WHERE deleted_at = 0 ORDER BY id DESC)  
UNION ALL  
(SELECT * FROM table WHERE deleted_at <> 0 ORDER BY id DESC)  
LIMIT 0,30

我不得不说,这个查询不会产生任何错误,结果就是我所期望的。 他们的订单不是很好。

3 个答案:

答案 0 :(得分:1)

使用子查询时无法保证排序。如果您希望按降序排序的结果,请使用:

(SELECT * FROM table WHERE deleted_at = 0)  
UNION ALL  
(SELECT * FROM table WHERE deleted_at <> 0)  
order by id desc
LIMIT 0,30;

但是,我认为您真正想要的查询是:

select *
from table
order by deleted_at = 0 desc, id desc
limit 0, 30;

这会先放置deleted_at = 0行,然后用其余数据填充数据。

注意:如果deleted_at可以为NULL并且您也想要将它们过滤掉,那么为此过滤添加where子句。

答案 1 :(得分:1)

from the manual

  

要将ORDER BY或LIMIT应用于单个SELECT,请将子句放在包含SELECT的括号内:   (选择一个FROM t1 WHERE a = 10 AND B = 1 ORDER by LIMIT 10)   联盟   (选择一个FROM t2 WHERE a = 11 AND B = 2 ORDER by LIMIT 10);

     

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

如果您需要它总计:

SELECT * FROM table WHERE deleted_at = 0
UNION ALL  
SELECT * FROM table WHERE deleted_at <> 0
ORDER BY deleted_at = 0 DESC, id DESC
LIMIT 0,30

但这源于:

SELECT * FROM table 
ORDER BY deleted_at = 0 DESC, id DESC
LIMIT 0,30

答案 2 :(得分:0)

因为您在UNION ALL之前应用ORDER BY语句只对数据的一部分发生,所以您希望将它应用于整个结果,它应该是这样的:

SELECT * FROM table WHERE deleted_at = 0  
UNION ALL  
SELECT * FROM table WHERE deleted_at <> 0 
ORDER BY id DESC
LIMIT 0,30