首页 > 解决方案 > Psql 查询:联合不保留来自 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

谁能解释为什么会这样?

标签: sqlpostgresqlsql-order-byunioncommon-table-expression

解决方案


文档很清楚,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;

请注意,我更改unionunion all; 您似乎不想对行进行重复数据删除(前者会这样做),因此后者已经足够好(而且效率更高)。


推荐阅读