【问题标题】:How to iterate over distinct dates in a table如何迭代表中的不同日期
【发布时间】:2021-10-21 20:21:45
【问题描述】:

我有下表:

id date gap
1 2020-01-01 3
2 2020-01-01 5
3 2020-01-01 8
4 2020-01-02 6
5 2020-01-02 10
6 2020-01-02 12

我想遍历不同的日期并获取具有最高“差距”值的两行。期望的结果:

id date gap
2 2020-01-01 5
3 2020-01-01 8
5 2020-01-02 10
6 2020-01-02 12

我尝试了以下方法

DO $$
DECLARE
    temprow record;
BEGIN
FOR temprow in
        SELECT DISTINCT date 
        FROM table
    LOOP
        SELECT *
        FROM table
        ORDER BY gap DESC
        LIMIT 2;
    END LOOP;
END;
$$;

给我以下错误:

错误:查询没有结果数据的目的地。

用 RETURN() 包装最后一个 SELECT 语句给出:

错误:RETURN 在返回 void 的函数中不能有参数

我不确定我是否需要一个循环,所以请随意提出一个没有循环的解决方案。

【问题讨论】:

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


    【解决方案1】:

    这可以使用窗口函数来完成:

    select id, "date", gap
    from (
      select id, "date", gap, 
             dense_rank() over (partition by "date" order by gap desc) as rnk
      from the_table
    ) t
    where rnk <= 2
    order by "date", gap;
    

    如果在同一日期有两行具有相同(最高)的差距,则两者都将被返回。如果您不想这样,请使用row_number() 而不是dense_rank()

    Online example

    【讨论】:

    • 是的,DENSE_RANKRANKROW_NUMBER 都是有效选项,具体取决于 OP 希望如何处理关系。
    【解决方案2】:

    你不需要循环也不需要 plpgsql。

    select l.* from 
    (
     select distinct "date" as dd from the_table
    ) t 
    cross join lateral
    (
     select * from the_table 
     where "date" = t.dd order by gap desc limit 2
    ) l
    order by "date", gap;
    

    几乎用简单的语言 - 对于每个不同的日期 dd 获取两行。

    【讨论】:

    • 是的,能够用几乎简单的英语表达您想要选择的内容是 SQL 的优势。我仍然更喜欢窗口方法,虽然英语听起来有点啰嗦“按间隔排列每个日期的行,然后保留所有前两行。
    • @ThorstenKettner 我同意,排名可以让你更好地控制。
    猜你喜欢
    • 2023-03-15
    • 2017-09-04
    • 1970-01-01
    • 2019-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 2017-02-09
    相关资源
    最近更新 更多