【发布时间】:2016-04-10 02:40:44
【问题描述】:
我正在尝试更好地理解 PostgreSQL (9.3) 窗口函数。假设我有一个简单的表格:
SimpleTable
id int,
tservice timestamp
并希望:
Select id, tservice , count(*) OVER (PARTITION BY id ....) as counter
from SimpleTable
SimpleTable 中的记录的 tservice 时间可以追溯到 40 年前,但是 计数需要仅限于每条记录的 tservice 时间戳之前的三年。
如何为 SimpleTable 中的每条记录生成计数?
推论问题:如何更改同一查询以添加今天日期前三年发生的所有记录的计数?
编辑#1:现在我明白这个问题在哪里模糊(我学到了一些东西:))。 使用下面的答案,我想获得 3 年的计数和当前日期的计数,例如:
3yrs prior current date
1, 100, '2001-01-01 00:00:00', 0 0
2, 100, '2002-01-01 00:00:00', 1 0
3, 100, '2003-01-01 00:00:00', 2 0
4, 100, '2004-01-01 00:00:00', 3 0
5, 100, '2005-01-01 00:00:00', 3 0
6, 100, '2006-01-01 00:00:00', 3 0
7, 100, '2007-01-01 00:00:00', 3 0
8, 100, '2008-01-01 00:00:00', 3 0
9, 100, '2009-01-01 00:00:00', 3 0
10, 100, '2010-01-01 00:00:00',3 0
11, 100, '2011-01-01 00:00:00',3 0
12, 100, '2012-01-01 00:00:00',3 0
13, 100, '2013-01-01 00:00:00',3 0
14, 100, '2014-01-01 00:00:00',3 1
15, 100, '2015-01-01 00:00:00',3 2
16, 100, '2016-01-01 00:00:00',3 3 (today is 2016-01-06)
编辑#2:这可以得到我需要的答案,但不使用窗口分区。我在想 PostgreSQL 没有实现带有间隔的 RANGE - 这是我认为这个问题所需要的。
select s1.recid, s1.tservice, s1.client_recid,
(select count(*) from simpletable s2
where (s1.tservice - s2.tservice)::INTERVAL <= interval '3 years' and
s2.tservice < s1.tservice and
s2.client_recid = s1.client_recid)
from simpletable s1
order by client_recid, tservice
在几十万条记录中,这在我的笔记本电脑上大约需要 10 秒。有更快的方法吗?
附录注意:使用 Erwin 概述的带有光标的函数式方法将执行时间减少到 146 毫秒。感谢大家的精彩教程。
【问题讨论】:
-
关于“每条记录服务前三年”的COUNT,请提供“样本数据”和“预期结果”
标签: database postgresql window-functions cumulative-sum