SQL 查询以使用突发事件获得 运行 总数

SQL query to get a running totals using a breaking event

部分城市有雨天或晴天的报告。每个标志值代表一个下雨事件(flag=1 Sunny day flag=0 Rainy day)。每一行我都需要产生一个结果,包括下雨那天在内的下雨前经过了多少天。例如,对于下面的 2017 年 10 月 10 日的城市“A”,预期结果是 2,计算 1/05 和 1/10,因为 1/10 下雨。我尝试使用 CTE,它适用于某些行,但不适用于所有行。每次下雨事件都会重置 运行 总数。所以每个雨天在上次下雨后都有自己的 运行 总数,并且不会从之前的雨天累积。

我在下面的 table 中有预期结果的列。

CREATE TABLE #Sample
  ([Date] datetime,
   [Name] char(1),
   [flag] bit,
   [expected_result] int
   );
GO

--drop table #Sample

INSERT INTO #Sample
VALUES
  ('1/1/2017','A',0,1),
  ('1/2/2017','B',0,1),
  ('1/3/2017','C',1,0),
  ('1/4/2017','D',0,1),
  ('1/5/2017','A',1,0),
  ('1/6/2017','C',1,0),
  ('1/7/2017','C',1,0),
  ('1/8/2017','B',0,1),
  ('1/9/2017','D',1,0),
  ('1/11/2017','C',0,4),
  ('1/10/2017','A',0,2),
  ('1/11/2017','A',0,1),
  ('1/12/2017','A',1,0),
  ('1/13/2017','A',1,0),
  ('1/14/2017','A',0,3),
  ('1/15/2017','D',0,2),
  ('1/16/2017','D',1,0);
GO

SELECT * FROM #Sample
order by Name,Date

我尝试了以下方法但没有成功

with t as 
(
SELECT S1.Date, S1.Name,
       --s1.[Count] AS [Count],
       S1.flag,
       SUM(CAST(S1.flag AS INT)) OVER(PARTITION BY S1.Name,S1.flag Order BY s1.[Name], S1.Date) AS Sunny_Days,
       [expected_result]
FROM #Sample S1
)
select  t.*, 
CASE WHEN flag=0 AND LAG(flag,1,0) OVER(PARTITION BY Name Order BY [Name], Date)=1 THEN
LAG(Sunny_Days,1,0)  OVER(PARTITION BY Name Order BY [Name], Date)+1
ELSE
0
END as Days_Transpired_Before_Rain from t
order by Name,Date

您描述的方式相当棘手。一种更简单的方法是根据每行上或之后的雨天数将组分配给行。

然后,每个下雨天都与之前的所有非下雨天组成一组。只需计算组的大小即可获得您想要的数量。

在SQL中:

select s.*,
       (case when flag = 0 then count(*) over (partition by name, grp) 
             else 0
        end) as calculated_result
from (select s.*,
             sum(case when flag = 0 then 1 else 0 end) over (partition by name order by date desc) as grp
      from sample s
     ) s
order by date

Here 是一个 db<>fiddle.