PostgreSQL:如何创建基于游标的分页,并对聚合结果和id进行排序?

ds97pgxw  于 2024-01-07  发布在  PostgreSQL
关注(0)|答案(1)|浏览(149)

我想为GraphQL创建一个基于光标的分页功能。下面是没有分页的数据。

SELECT 
    "Post"."id",
    COALESCE(SUM("PostVote"."value"), 0)::int as "voteScore"
FROM "Post"
LEFT JOIN "PostVote" ON "PostVote"."postId" = "Post"."id"
WHERE "Post"."questionId" = 28
GROUP BY "Post"."id"
ORDER BY "voteScore" DESC, id ASC

字符串
| ID| voteScore|
| --|--|
| 32 | 2 |
| 30 | 0 |
| 31 | 0 |
| 33 | 0 |
| 34 | 0 |
| 29 |-1个|
当我尝试使用LIMIT 2和30之后的id(cursor)实现基于游标的分页时,它会产生不正确的结果。

SELECT 
    "Post"."id",
    COALESCE(SUM("PostVote"."value"), 0)::int as "voteScore"
FROM "Post"
LEFT JOIN "PostVote" ON "PostVote"."postId" = "Post"."id"
WHERE "Post"."questionId" = 28
    AND "Post"."id" > 30 -- new
GROUP BY "Post"."id"
ORDER BY "voteScore" DESC, id ASC
LIMIT 2 -- new


| ID| voteScore|
| --|--|
| 32 | 2 |
| 31 | 0 |
我的预期结果是:
| ID| voteScore|
| --|--|
| 31 | 0 |
| 33 | 0 |
如何在不像上面第一个表那样分页的情况下维护顺序?我创建的查询似乎只关心id,而不关心聚合数据voteScore。基本上我想按“voteScore”排序。

xu3bshqb

xu3bshqb1#

你不能无条件地在id >30上过滤,因为当分页到那个程度时,你会错过29行。所以你只需要在聚合的关系中应用id过滤器:

SELECT
    "Post"."id",
    COALESCE(SUM("PostVote"."value"), 0)::int as "voteScore"
FROM "Post"
LEFT JOIN "PostVote" ON "PostVote"."postId" = "Post"."id"
WHERE "Post"."questionId" = 28
GROUP BY "Post"."id"  
HAVING COALESCE(SUM("PostVote"."value"), 0)::int <0 or COALESCE(SUM("PostVote"."value"), 0)::int =0 and id >30
ORDER BY "voteScore" DESC, id ASC
LIMIT 2

字符串
您可以通过使用元组比较来使其稍微更清晰一些,但是由于它们是按不同的方向排序的,因此如果没有一些技巧,这将无法工作。

SELECT
    "Post"."id",
    COALESCE(SUM("PostVote"."value"), 0)::int as "voteScore"
FROM "Post"
LEFT JOIN "PostVote" ON "PostVote"."postId" = "Post"."id"
WHERE "Post"."questionId" = 28
GROUP BY "Post"."id"
HAVING (COALESCE(SUM("PostVote"."value"), 0)::int,-id)  < (0,-30)
ORDER BY "voteScore" DESC, -id desc
LIMIT 2;

相关问题