PostgreSQL - 将底部的 N 个结果切片并将它们移动到顶部
PostgreSQL - Slice the bottom N results and move them to the top
比方说,我有一个像这样检索的电子邮件地址列表:
SELECT email FROM users ORDER BY email
这个returns:
a@email.com
b@email.com
c@email.com
...
x@email.com
y@email.com
z@email.com
我想获取此结果集,将底部的 3 封电子邮件切分并移至顶部,这样您会看到如下结果集:
x@email.com
y@email.com
z@email.com -- Note x-z is here
a@email.com
b@email.com
c@email.com
...
u@email.com
v@email.com
w@email.com
有没有办法在 SQL 中做到这一点?出于内存原因,我不想在应用程序端执行此操作。
如果您知道这些值为 "x" 或更大,您可以简单地执行以下操作:
order by (case when email >= 'x@email.com' then 1 else 2 end),
email
否则,您可以使用row_number()
:
select email
from (select email, row_number() over (order by email desc) as seqnum
from users u
) u
order by (case when seqnum <= 3 then 1 else 2 end),
email;
这是一个具有 window 函数 row_number()
和 count()
的版本:
SELECT email
FROM (
SELECT row_number() OVER (ORDER BY email), count(*) OVER (), email
FROM users
) sq1
ORDER BY count - 3 >= row_number, email;
假设 email
定义为 UNIQUE NOT NULL
。否则你需要做更多。
SELECT email
FROM (SELECT email, row_number() OVER (ORDER BY email DESC) AS rn FROM users) sub
ORDER BY (rn > 3), rn DESC;
在 Postgres 中,您可以按 boolean
表达式排序。 FALSE
在 TRUE
之前排序。更多:
- Sorting null values after all others, except special
其次,按计算的行号(rn
)降序排序。下次不要按(更昂贵的)文本列 email
排序。更短更简单 - 用 EXPLAIN ANALYZE
测试,它也应该更快。
比方说,我有一个像这样检索的电子邮件地址列表:
SELECT email FROM users ORDER BY email
这个returns:
a@email.com
b@email.com
c@email.com
...
x@email.com
y@email.com
z@email.com
我想获取此结果集,将底部的 3 封电子邮件切分并移至顶部,这样您会看到如下结果集:
x@email.com
y@email.com
z@email.com -- Note x-z is here
a@email.com
b@email.com
c@email.com
...
u@email.com
v@email.com
w@email.com
有没有办法在 SQL 中做到这一点?出于内存原因,我不想在应用程序端执行此操作。
如果您知道这些值为 "x" 或更大,您可以简单地执行以下操作:
order by (case when email >= 'x@email.com' then 1 else 2 end),
email
否则,您可以使用row_number()
:
select email
from (select email, row_number() over (order by email desc) as seqnum
from users u
) u
order by (case when seqnum <= 3 then 1 else 2 end),
email;
这是一个具有 window 函数 row_number()
和 count()
的版本:
SELECT email
FROM (
SELECT row_number() OVER (ORDER BY email), count(*) OVER (), email
FROM users
) sq1
ORDER BY count - 3 >= row_number, email;
假设 email
定义为 UNIQUE NOT NULL
。否则你需要做更多。
SELECT email
FROM (SELECT email, row_number() OVER (ORDER BY email DESC) AS rn FROM users) sub
ORDER BY (rn > 3), rn DESC;
在 Postgres 中,您可以按 boolean
表达式排序。 FALSE
在 TRUE
之前排序。更多:
- Sorting null values after all others, except special
其次,按计算的行号(rn
)降序排序。下次不要按(更昂贵的)文本列 email
排序。更短更简单 - 用 EXPLAIN ANALYZE
测试,它也应该更快。