Gan*_*row 9 postgresql order-by
我知道IN
Postgres 中的语句不能保证返回行的顺序。例如,如果我这样做:
SELECT users.id FROM users WHERE users.id IN (13589, 16674, 13588)
Run Code Online (Sandbox Code Playgroud)
我可能会得到这样的结果:
16674
13588
13589
Run Code Online (Sandbox Code Playgroud)
但是,我希望返回的行尊重IN
列表中的顺序,所以我在网上找到的解决方案很少,例如:
SELECT users.id FROM users WHERE users.id IN (13589, 16674, 13588)
ORDER BY POSITION(id::text in '(13589, 16674, 13588)')
Run Code Online (Sandbox Code Playgroud)
或者
SELECT users.id FROM users WHERE users.id IN (13589, 16674, 13588)
ORDER BY id = 13589 desc,
id = 16674 desc,
id = 13588 desc;
Run Code Online (Sandbox Code Playgroud)
我想知道是否有更好的方法来做到这一点,或者更好但更有效?
WITH ORDINALITY
在 Postgres 9.4+随 Postgres 9.4 引入。手册:
When a function in the
FROM
clause is suffixed byWITH ORDINALITY,
abigint
column is appended to the output which starts from 1 and increments by 1 for each row of the function's output. This is most useful in the case of set returning functions such asunnest()
.
SELECT u.*
FROM unnest('{13589, 16674, 13588}'::int[]) WITH ORDINALITY AS x(id, order_nr)
JOIN users u USING (id)
ORDER BY x.order_nr;
Run Code Online (Sandbox Code Playgroud)
x IN (set)
statements are rewritten internally in Postgres to x = ANY (array)
, which is equivalent:
SELECT users.id FROM users WHERE users.id = ANY ('{13589, 16674, 13588}')
Run Code Online (Sandbox Code Playgroud)
You can see for yourself with EXPLAIN
.
For now, to preserve the order of elements, you could:
SELECT u.*
FROM (
SELECT arr, generate_subscripts(arr, 1) AS order_nr
FROM (SELECT '{13589, 16674, 13588}'::int[]) t(arr)
) x
JOIN users u ON u.id = x.arr[x.order_nr]
ORDER BY x.order_nr;
Run Code Online (Sandbox Code Playgroud)
db<>fiddle here
Further reading:
归档时间: |
|
查看次数: |
9389 次 |
最近记录: |