sql - 获取列表中每个 ID 的前 3 行

标签 sql postgresql greatest-n-per-group

我有这个 SQL 查询来获取列表中每个 ID 的相关注释:

SELECT comments.id, comments.body, comments.created_at
     , comments.like_count, comments.post_id
FROM   comments
WHERE  comments.is_active AND comments.is_show 
AND    comments.post_id in (1, 7, 9, 11, 3)
GROUP BY comments.id
ORDER BY comments.id
LIMIT 3   <----- this is not working correctly!

我想获取给定列表中每个帖子 ID 的前 3 条评论(1、7、9、11、3)。
如何实现这一目标?

最佳答案

这将削弱迄今为止建议的解决方案的性能:

SELECT c.*
FROM   unnest('{1, 7, 9, 11, 3}'::int[]) AS p(post_id)  -- assuming integer?
CROSS  JOIN LATERAL (
   SELECT id, body, created_at, like_count, post_id
   FROM   comments c
   WHERE  is_active
   AND    is_show 
   AND    c.post_id = p.post_id
   ORDER  BY like_count DESC NULLS LAST  -- assuming this defines "top"?
   LIMIT  3
   ) c
ORDER  BY id, like_count DESC NULLS LAST;  -- see below

需要在(post_id, like_count)上建立索引才能快速

与使用 row_number() 的缓慢解决方案(必须扫描整个评论表)不同,这可以轻松地从索引中识别每个 post_id 的前 3 条评论。对于大表,速度要快几个数量级。

参见:

如果 like_count 定义为 NOT NULL(可能应该如此),您可以简化为 ORDER BY id, like_count DESC。否则,您需要DESC NULLS LAST,并且最佳索引位于(post_id, like_count DESC NULLS LAST)。关于这一点:

关于sql - 获取列表中每个 ID 的前 3 行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73255603/

相关文章:

sql - 我可以将 Word 文档存储在 PostgreSQL 数据库中吗?

sql - 用于显示的口语年龄计算

sql - 更新在 CTE 中较早插入的行

mysql - 在没有主键的情况下检索每个组中的最后一条记录

sql - 如何评估两个表列单元格的值?

mysql - 计算投票结果

python - 无法使用 django + nginx 上传媒体文件

mysql - SQL 仅选择列上具有最大值的行

MySQL - 如何对 "nested"数据集使用 GROUP BY/ORDER BY?

sql - 如何使带有 FILTER 子句的查询运行得更快?