PostgreSQL 中的窗口函数尾随日期
Posted
技术标签:
【中文标题】PostgreSQL 中的窗口函数尾随日期【英文标题】:Window function trailing dates in PostgreSQL 【发布时间】:2012-11-13 21:07:50 【问题描述】:我正在尝试编写一个查询来比较给定计算机今天的平均连接数与 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;
编写此类查询的最佳方法是什么?窗口函数方法是否有意义,或者是否有更优化的方法来处理大型表的情况?
【问题讨论】:
请在所有问题中显示您的 PostgreSQL 版本,以及错误消息的确切文本。 【参考方案1】:部分问题是您选择了一个糟糕的列名"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 模式下允许。它们表明帧以 当前行之前或之后的行数。值必须是 一个不包含任何变量的整数表达式,聚合 函数或窗口函数。
我只会在输入行上使用带有 WHERE
过滤器的普通 GROUP BY
。
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;
【讨论】:
【参考方案2】:为了得到……
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 中。
【讨论】:
以上是关于PostgreSQL 中的窗口函数尾随日期的主要内容,如果未能解决你的问题,请参考以下文章
PostgreSQL 中的 PERCENTILE_DISC() 作为窗口函数
使用窗口函数确定 PostgreSQL 中的 30 天运行计数