【问题标题】:Get top 5 rows per row in related table获取相关表中每行的前 5 行
【发布时间】:2015-02-28 21:48:31
【问题描述】:

我使用的是 PostgreSQL 9.4。

我有 workout lists 和一个关联的连接表,列出了该列表中的哪些锻炼。

我想返回列表中每个锻炼的 5 个最新结果。

下面返回每个结果,如果我附加LIMIT 5,我总共只会得到 5 个结果,而不是每次锻炼 5 个。我如何在 SQL 中执行此操作?

SELECT "results".* FROM "results" 
WHERE "results"."user_id" = 1
  AND workout_id IN (SELECT workout_id FROM workout_list_join_table
                     WHERE workout_list_id = 5) 
ORDER BY "results"."done_at" DESC

【问题讨论】:

标签: sql postgresql greatest-n-per-group postgresql-9.4


【解决方案1】:

您可以使用window function

select *
from (
    SELECT results.*, 
           row_number() over (partition by workout_id order by done_at desc) as rn
    FROM results 
    WHERE results.user_id = 1
      AND workout_id IN (SELECT workout_id 
                         FROM workout_list_join_table 
                         WHERE workout_list_id = 5) 
) t
where rn <= 5
ORDER BY done_at DESC;

【讨论】:

  • 它可以工作,但在大型结果集上可能会变慢。在 9.4 中,您可以使用 LATERAL 来限制数据库必须处理的数据量
【解决方案2】:

从 9.4 版开始,您还可以使用 LATERAL:

SELECT  r.*
FROM    workout_list_join_table w
    JOIN LATERAL(SELECT * FROM results r WHERE r.workout_id = w.workout_id AND user_id = 1 ORDER BY r.done_at DESC LIMIT 5) r ON (true)
WHERE   workout_list_id = 5
ORDER BY 
    r.done_at DESC;

当使用大表时,由于更好的查询计划,这可能比窗口函数快得多。 LATERAL 不需要所有数据,它可以限制子查询中的行数。查看 Markus Winand 的这些幻灯片以获取更多信息:Modern SQL in PostgreSQL

【讨论】:

  • LATERAL 随附 pg 9.3。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-07
  • 1970-01-01
  • 2021-12-29
相关资源
最近更新 更多