问题描述
with cte1 as (select salary from employees order by salary desc),cte2 as (select 850) select * from cte1 union select * from cte2;
cte1是按薪金列排序的,而cte2不是。我希望将cte2的结果附加到cte1的结果中,同时保留cte1的结果顺序。但这没有发生。
如果我在不带第二个cte的情况下运行上述查询而没有联合,则结果按预期顺序显示,但是当存在联合时,该顺序就会混乱。
无联合查询
with cte1 as (select salary from employees order by salary desc),cte2 as (select 850) select * from cte1;
salary
--------
1000
900
800
700
600
500
使用联合:
with cte1 as (select salary from employees order by salary desc),cte2 as (select 850) select * from cte1 union select * from cte2;
salary
--------
850
800
700
900
500
600
1000
任何人都可以解释为什么会这样吗?
解决方法
documentation很清楚,union
不保证行的顺序:
UNION
有效地将query2的结果附加到query1的结果上(尽管不能保证这是实际返回行的顺序)。
如果要对结果进行排序,则在外部查询中使用order by
;对于您的用例,这需要跟踪每行来自哪个cte
with
cte1 (salary,which) as (select salary,1 from employees),cte2 (salary,which) as (select 850,2)
select salary from cte1
union all
select salary from cte2
order by which,salary desc;
请注意,我将union
更改为union all
;似乎您不想对行进行重复数据删除(前者确实如此),所以后者足够好(而且效率更高)。
order by
不是select
的一部分。 select
给出一个表,该表是一个集合,没有顺序。您可以在末尾order by
进行操作,显然也可以在并集中进行操作,但是例如,您不能与有序集(至少不是在sybase中)连接。
UNION
子句减少重复的行。这种减少可以通过两种技术来完成:
- 使用has表-哈希不能保留顺序
- 使用排序并删除随后的相等行-这种排序会破坏原始顺序。
如果要阻止此行为,请使用UNION ALL
子句,这不会减少多余的行(重复)。