PostgreSQL中的窗口函数尾随日期

时间:2012-11-13 21:07:50

标签: sql postgresql window-functions

我正在尝试编写一个查询来比较当前给定计算机的平均连接数与7到14天之前的平均连接数。我认为这最好由窗口函数处理,但我无法使日期的语法正确。

假设我有一个名为iptable的IP地址和连接记录表,其中包含soucreip,destinationip,timestamp作为列。以下是我在前7天窗口中尝试获取每个sourceip的计数的查询:

select 
  sourceip, 
  destinationip, 
  timestamp, 
  count(*) OVER (PARTITION BY sourceip order by timestamp
                 RANGE BETWEEN now() - '7 day'::Interval PRECEDING
                               now() - '14 day'::Interval FOLLOWING)
from
 iptable;

编写这种类型的查询的最佳方法是,窗函数方法是否有意义,还是有更优化的方法来处理大型表的情况?

2 个答案:

答案 0 :(得分:6)

您的部分问题是您选择了一个糟糕的列名"timestamp"timestamp是内置数据类型的名称,因此要将其用作列名,您必须"double quote"无处不在。

但是,这不是全部。您的窗口函数语法错误。见window function syntax。你忘记了AND;它是RANGE BETWEEN .. PRECEDING AND ... FOLLOWING

此外,虽然这不是问题的原因,但您应该使用SQL标准current_timestamp而不是now()

这会让你遇到一个新错误:

CREATE TABLE iptable ( sourceip cidr, destinationip cidr, "timestamp" timestamptz);

regress=> select 
  sourceip, 
  destinationip, 
  timestamp, 
  count(*) OVER (PARTITION BY sourceip order by "timestamp" RANGE BETWEEN current_timestamp - '7 day'::Interval PRECEDING AND current_timestamp - '14 day'::Interval FOLLOWING)

from
 iptable;
ERROR:  RANGE PRECEDING is only supported with UNBOUNDED
LINE 5: ... OVER (PARTITION BY sourceip order by "timestamp" RANGE BETW...
                                                             ^

这表明当前的窗口函数实现不会按照您的意愿执行。不幸的是

  

值PRECEDING和值FOLLOWING个案目前仅限   在ROWS模式下允许。它们表示框架的开始或结束   当前行之前或之后的许多行的行。价值必须是   不包含任何变量的整数表达式,聚合   功能或窗口功能。

相反,我只是在输入行上使用带有GROUP BY过滤器的普通WHERE

select 
  sourceip,
  count(sourceip) AS n_conns_7_to_14_days_ago
from
 iptable
WHERE age("timestamp") BETWEEN INTERVAL '7' DAY AND INTERVAL '14' DAY
GROUP BY sourceip;

答案 1 :(得分:4)

要得到......

  

7天到14天之间的平均连接数

SELECT sourceip, destinationip, timestamp, count(*) AS ct
FROM   iptable
WHERE  "timestamp" BETWEEN now() - '14 day'::interval
                   AND     now() -  '7 day'::interval
GROUP BY 1,2,3;

只需使用普通的聚合函数 并且不要使用timestamp作为列名。它是SQL标准中的protected word,部分保留在PostgreSQL中。