【问题标题】:Rewriting a window function using rank( ) in terms of group by使用 rank( ) 根据 group by 重写窗口函数
【发布时间】:2012-09-12 19:15:24
【问题描述】:

我有一个窗口函数,它使用 rank() 操作将最近的 DHCP 日志事件与 IP 地址相匹配,从而将 IP 与主机名相关联。问题是查询不能很好地扩展到大型数据集,因此我想尝试根据 group by 重写它,但我没有成功。

create table large_table as
select column1, column2, column3, column4, column5, column6
from
(
  select 
    a.column1, a.column2, a.start_time,
    rank() OVER( 
      PARTITION BY a.column2, a.column1 order by a.start_time DESC 
    ) as rank,
    last_value( a.column3) OVER (
      PARTITION BY a.column2, a.column1 order by a.start_time ASC
      RANGE BETWEEN unbounded preceding and unbounded following 
    ) as column3,
    a.column4, a.column5, a.column6
  from 
    (table2 s 
      INNER JOIN table3 t 
      ON s.column2=t.column2 and s.event_time > t.start_time 
    ) a
 ) b
 where rank =1;

问题 1: 我们如何使用 group by 而不是窗口函数来重写上面的查询?

【问题讨论】:

  • 该查询是否必须与输出完全匹配?能否给表和列起一些有意义的名称,以便我们更好地把握问题。
  • 您需要为table2table3 提供表定义。列的来源隐藏在(完全没有意义的)子查询a 中。
  • @ErwinBrandstetter:您的尝试看起来很合理(出色的逆向工程),但似乎缺少 lag(1) 结果。
  • @wildplasser:我偶然发现了last_value() 表达式。 ORDER BY 没有定义“最后一个值”。它产生任意的、特定于实现的结果。原始查询实际上已损坏,并且未经 OP 澄清就无法重写。我删除的答案假设太多,一半不正确。
  • 表定义和示例数据真的很有帮助。

标签: sql postgresql group-by


【解决方案1】:

我不认为以这种方式将窗口编写为 group-by 将是一个成功的策略。当您将表中的聚合连接回主表时,这将导致严重的性能问题。

更好的方法是使用 plpgsql 和一个在循环中添加窗口信息的函数。例如,可以这样添加行号:

CREATE OR REPLACE FUNCTION foo_with_rownumber () RETURNS SETOF foo_with_rownumber
LANGUAGE PLPGSQL AS $$
DECLARE out_val foo_with_rownumber;
        iter int;
BEGIN
    iter := 1;
    FOR out_val IN select f.*, 0 FROM foo order by bar
    LOOP
        out_val.rownumber = iter;
        return next out_val;
        iter := iter + 1;
    END LOOP;
END;
$$;

rank() 添加起来会稍微复杂一些,所以这应该会让你继续前进。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-19
    • 1970-01-01
    • 2022-06-14
    • 1970-01-01
    • 1970-01-01
    • 2020-12-16
    • 2021-12-09
    相关资源
    最近更新 更多