PostgreSQL中的窗口函数跟踪日期

PostgreSQL中的窗口函数跟踪日期,sql,postgresql,window-functions,Sql,Postgresql,Window Functions,我正在尝试编写一个查询,将给定计算机今天的平均连接数与7到14天前的平均连接数进行比较。我认为这最好由一个窗口函数来处理,但我无法获得日期的正确语法 假设我有一个名为iptable的IP地址和连接记录表,其中soucrep、destinationip、timestamp作为列。以下是我在前7天窗口中尝试的查询,以获取每个sourceip的计数: select sourceip, destinationip, timestamp, count(*) OVER (PARTIT

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

假设我有一个名为iptable的IP地址和连接记录表,其中soucrep、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;

编写此类查询的最佳方法是什么?窗口函数方法有意义吗?还是有更优化的方法来处理大型表的情况?

部分问题是您选择了一个糟糕的列名,
“timestamp”
timestamp
是内置数据类型的名称,因此要将其用作列名,必须
“双引号”
将其置于任何位置

不过,这还不是全部。您的窗口函数语法错误。看见您忘记了
;它的
范围介于。。前面和。。。下面是

此外,尽管这不是问题的原因,但您应该使用SQL标准
current\u 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...
                                                             ^
这表明当前的窗口函数实现不会执行您希望它执行的操作。可悲的是

当前仅在前面的值和后面的值情况下使用 在行模式下允许。它们表示帧以开始或结束 在当前行之前或之后包含多行的行。价值必须是 不包含任何变量的整数表达式,聚合 函数或窗口函数

相反,我只是在输入行上使用一个普通的
groupby
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;
得到

7到14天前的平均连接数

只需使用普通聚合函数。

并且不要使用
时间戳
作为列名。这是SQL标准中的一个版本,部分保留n PostgreSQL。

请在所有问题中显示您的PostgreSQL版本,以及错误消息的确切文本。
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;