Psql 查询:联合不保留来自 cte 的行的顺序
Psql query : Union is not preserving the order of rows coming from 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
谁能解释一下为什么会这样?
documentation 很明显 union
不保证行的顺序:
UNION
effectively appends the result of query2 to the result of query1 (although there is no guarantee that this is the order in which the rows are actually returned).
如果你希望结果是有序的,那么在外层查询中使用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
给出一个table,这是一个集合,没有顺序。你可以在最后做一个 order by
,显然也可以在联合中做,但是例如你不能加入一个有序集(至少在 sybase 中不行)。
UNION
子句减少重复行。这种减少可以通过两种技术来完成:
- 使用 table - 散列不保留顺序
- 使用排序并删除相等的后续行 - 这种排序打破了原始顺序。
如果您想阻止此行为,请使用 UNION ALL
子句,这不会减少冗余行(重复)。
我有这个问题:
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
effectively appends the result of query2 to the result of query1 (although there is no guarantee that this is the order in which the rows are actually returned).
如果你希望结果是有序的,那么在外层查询中使用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
给出一个table,这是一个集合,没有顺序。你可以在最后做一个 order by
,显然也可以在联合中做,但是例如你不能加入一个有序集(至少在 sybase 中不行)。
UNION
子句减少重复行。这种减少可以通过两种技术来完成:
- 使用 table - 散列不保留顺序
- 使用排序并删除相等的后续行 - 这种排序打破了原始顺序。
如果您想阻止此行为,请使用 UNION ALL
子句,这不会减少冗余行(重复)。