使用rank()按group by重写窗口函数

时间:2012-09-12 19:15:25

标签: sql postgresql group-by

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

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而不是window函数重写上述查询?

1 个答案:

答案 0 :(得分:1)

我认为以这种方式制作以分组方式编写的窗口并不是一个成功的策略。当您将表中的聚合反馈到主表时,这会导致严重的性能问题。

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

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()只会稍微复杂一点,所以这应该让你去。