SQL:汇总满足特定条件的滚动周 window 分区内的行数

SQL: sum the number of rows within a partition for a rolling week window where a specific condition is met

目标:统计在连续 4 周的时间里,有多少人在一周、两周、三周和四个星期内都低于目标 window。

我们的想法是使用按工作周 (WW) 划分的分析函数来计算在任何给定周内低于目标的人数。一个人不必连续数周处于目标之下。如果一个人至少有一个星期没有达到目标,不管是哪个工作周,然后计算它。如果他们在任何两周内都低于目标,请计算在内。

IF(分数 < 50, 1, 0) AS 目标。

week      person  target
WW 31     name_x    1
WW 31     name_y    1
WW 31     name_z    0
--------------------
WW 32     name_x    1
WW 32     name_y    1
WW 32     name_z    0
--------------------
WW 33     name_x    0
WW 33     name_y    1
WW 33     name_z    0
--------------------
WW 34     name_x    1
WW 34     name_y    1
WW 34     name_z    0

期望的输出将是一个 table,我可以从中构建这样的可视化,其中 y 轴是一条线,用于计算符合 1、2、3 和 4 目标的人数周。 VISUALIZATION

我试过这样的东西

SUM(CASE WHEN target = 1 THEN 1 ELSE 0 END) OVER(PARTITION BY week)

这适用于计算达不到目标至少一周的人数,但我正在努力计算如何计算达不到目标至少 2、3 或 4 周的人数。

您可以使用 LAG() Window Function:

查看前几周的目标

lag(x[, offset[, default_value]]) → [same as input]

Returns the value at offset rows before the current row in the window Offsets start at 0, which is the current row. The offset can be any scalar expression. The default offset is 1. If the offset is null or larger than the window, the default_value is returned, or if it is not specified null is returned.

与此类似的查询应该会为您提供所需的结果:

with data_table as
(
   select week, person, target
   ,LAG(target,1,null)OVER(PARTITION BY person ORDER BY week) target_1w_ago
   ,LAG(target,2,null)OVER(PARTITION BY person ORDER BY week) target_2w_ago
   ,LAG(target,3,null)OVER(PARTITION BY person ORDER BY week) target_3w_ago
   from table
)
select week
,sum(target) "Weeks under 1"
,sum(case when target=1 and target_1w_ago=1 then 1 else 0 end) "Weeks under 2"
,sum(case when target=1 and target_1w_ago=1 and target_2w_ago=1 then 1 else 0 end) "Weeks under 3"
,sum(case when target=1 and target_1w_ago=1 and target_2w_ago=1 and target_3w_ago=1 then 1 else 0 end) "Weeks under 4"
from data_table
group by week
order by week