Psql查询:Union没有保留来自cte的行的顺序



我有这个查询:

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子句减少重复行。这种减少可以通过两种技术来实现:

  1. 使用has表-哈希不能保持顺序
  2. 使用排序并删除后面相等的行-这种排序会破坏原始顺序

如果要阻止此行为,请使用UNION ALL子句,该子句不会减少冗余行(重复行(。

order by不是select的一部分。select给出了一个表,它是一个集合,没有次序。您可以在末尾执行order by,显然也可以在并集中执行,但例如,您不能使用有序集进行联接(至少在sybase中不能(。

最新更新