【发布时间】:2014-04-09 03:11:21
【问题描述】:
我有不同公司的每日时间序列(实际上是工作日),我使用 PostgreSQL。还有一个指标变量(称为标志)在大多数情况下取值为 0,在一些罕见的事件日取值为 1。如果一个公司的指标变量取值为 1,我想进一步调查相应公司从该事件前两天到事件后一天的条目。让我将其称为 [-2,1] 窗口,事件日为第 0 天。
我正在使用以下查询
CREATE TABLE test AS
WITH cte AS (
SELECT *
, MAX(flag) OVER(PARTITION BY company ORDER BY day
ROWS BETWEEN 1 preceding AND 2 following) Lead1
FROM mytable)
SELECT *
FROM cte
WHERE Lead1 = 1
ORDER BY day,company
查询取事件发生前2天到事件发生后1天的条目,为发生事件的公司。 查询对所有事件执行此操作。
这是结果表的一小部分。
day company flag
2012-01-23 A 0
2012-01-24 A 0
2012-01-25 A 1
2012-01-25 B 0
2012-01-26 A 0
2012-01-26 B 0
2012-01-27 B 1
2012-01-30 B 0
2013-01-10 A 0
2013-01-11 A 0
2013-01-14 A 1
现在我想分别对每个 [-2,1] 窗口进行进一步的计算。所以我需要一个变量来识别每个 [-2,1] 窗口。这个想法是我用变量“发生”计算每个公司的窗口数量,以便在进一步计算中我可以使用该子句
GROUP BY company, occur
因此我想要的输出如下所示:
day company flag occur
2012-01-23 A 0 1
2012-01-24 A 0 1
2012-01-25 A 1 1
2012-01-25 B 0 1
2012-01-26 A 0 1
2012-01-26 B 0 1
2012-01-27 B 1 1
2012-01-30 B 0 1
2013-01-10 A 0 2
2013-01-11 A 0 2
2013-01-14 A 1 2
在示例中,公司 B 仅出现一次 (occur = 1)。但是A公司出现了两次。第一次从 2012-01-23 到 2012-01-26。第二次是从 2013-01-10 到 2013-01-14。公司 A 的第二个时间范围不包括事件日 (-2,-1,0,1) 周围的所有四天,因为该公司在该时间范围结束之前离开了数据集。
正如我所说,我正在处理工作日。我不在乎假期,我有周一到周五的数据。之前我写了以下函数:
CREATE OR REPLACE FUNCTION addbusinessdays(date, integer)
RETURNS date AS
$BODY$
WITH alldates AS (
SELECT i,
$1 + (i * CASE WHEN $2 < 0 THEN -1 ELSE 1 END) AS date
FROM generate_series(0,(ABS($2) + 5)*2) i
),
days AS (
SELECT i, date, EXTRACT('dow' FROM date) AS dow
FROM alldates
),
businessdays AS (
SELECT i, date, d.dow FROM days d
WHERE d.dow BETWEEN 1 AND 5
ORDER BY i
)
-- adding business days to a date --
SELECT date FROM businessdays WHERE
CASE WHEN $2 > 0 THEN date >=$1 WHEN $2 < 0
THEN date <=$1 ELSE date =$1 END
LIMIT 1
offset ABS($2)
$BODY$
LANGUAGE 'sql' VOLATILE;
它可以从给定日期添加/减去工作日,并像这样工作:
select * from addbusinessdays('2013-01-14',-2)
2013-01-10 提供结果。所以在 Jakub 的方法中,我们可以将倒数第二行和倒数第三行改为
w.day BETWEEN addbusinessdays(t1.day, -2) AND addbusinessdays(t1.day, 1)
并且可以处理工作日。
【问题讨论】:
-
你如何“定义”一个窗口?
-
窗口是指给定公司的 flag = 1 那天周围的日子。因此,将标志日视为第 0 天,[-2,1] 窗口是从前 2 天到后 1 天的时间段。 @MarkLaREZZA
-
那么一个窗口总是有4天?
-
是的,理论上窗口总是 4 天,但对于某些公司,我可能没有全部 4 天的数据。 @MarkLaREZZA
-
知道了 - 谢谢。我想我最初误读了这篇文章。
标签: sql postgresql time-series window-functions