我有这个查询:
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
有人能解释一下为什么会发生这种事吗?
文档清楚地表明,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
;您似乎不想对行进行重复数据消除(前者是这样做的(,因此后者足够好(而且更高效(。
UNION
子句减少重复行。这种减少可以通过两种技术来实现:
- 使用has表-哈希不能保持顺序
- 使用排序并删除后面相等的行-这种排序会破坏原始顺序
如果要阻止此行为,请使用UNION ALL
子句,该子句不会减少冗余行(重复行(。
order by
不是select
的一部分。select
给出了一个表,它是一个集合,没有次序。您可以在末尾执行order by
,显然也可以在并集中执行,但例如,您不能使用有序集进行联接(至少在sybase中不能(。