我的数据集包括每天(实际上是工作日,但对于答案来说无关紧要)不同公司的时间序列,我使用PostgreSQL。我的数据集中有一个指标变量,取值为1,-1,大多数时间为0.为了更好的问题可读性,我指的是指标变量不等于零作为指标天数的日子。
因此,对于前三天同一公司的另一个指标日之前的所有指标日,指标变量应更新为零。
我们可以使用以下示例数据集:
day company indicator
2012-01-04 A 0
2012-01-04 B 0
2012-01-05 A 0
2012-01-05 B -1
2012-01-06 A 0
2012-01-06 B 0
2012-01-09 A 0
2012-01-09 B 0
2012-01-10 A 0
2012-01-10 B 1
2012-01-11 A 1
2012-01-11 B 1
2012-01-12 A 0
2012-01-12 B 0
2012-01-13 A 1
2012-01-13 B 1
因此,必须更新为零的指标值为:2012-01-10公司B的条目,2012-01-11公司B的条目和2012-01-13两个条目,因为所有这些都是在3个工作日内同一公司的另一个指标日之前。
我尝试了以下
UPDATE test SET indicator = 0
WHERE day IN (
SELECT day
FROM (
SELECT company, day,
COUNT(CASE WHEN indicator <> 0 THEN 1 END)
OVER (PARTITION BY company ORDER BY day
ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) As cnt
FROM test
) alias
WHERE cnt >= 2)
这个想法是计算指标变量在当天和前3天不等于零的日子。如果计数超过1,则将指标值更新为零。不幸的是,它无法区分公司。因此,它在示例数据中的作用是在2012-01-11,它还将公司A的条目更新为零,因为在B的指示日前一天。
也许我需要像“按公司划分”这样的更新,但它不存在。
您有任何想法如何修复它,或者如何用另一种方法解决我的问题?
答案 0 :(得分:1)
Postgresql允许您为IN语句使用多个列,因此我认为您只需将查询更改为:
UPDATE test SET indicator = 0
WHERE (day, company) IN (
SELECT day, company
FROM (
SELECT company, day,
COUNT(CASE WHEN indicator <> 0 THEN 1 END)
OVER (PARTITION BY company ORDER BY day
ROWS BETWEEN 3 PRECEDING AND CURRENT ROW) As cnt
FROM test
) alias
WHERE cnt >= 2)
获得您需要的结果。
<强> Example on SQL Fiddle 强>