简体   繁体   English

SQL 查询使用中断事件获取运行总计

[英]SQL query to get a running totals using a breaking event

There are cities with reports of rainy day or sunny day.有些城市有雨天或晴天的报告。 Each flag value represents a rain event(flag=1 Sunny day flag=0 Rainy day).每个标志值代表一个降雨事件(标志=1 晴天标志=0 雨天)。 Each row I need to produce a result how many days transpired before the rain inclusive of the day it rained.每一行我都需要产生一个结果,包括下雨天之前发生了多少天。 For example for the city "A" below on 1/10/2017 the expected result is 2 counting 1/05 and 1/10 as it rained on 1/10.例如,对于下面 2017 年 1 月 10 日的城市“A”,预期结果是 2,计算 1/05 和 1/10,因为 1/10 下雨。 I tried with CTE which works for some rows but not all of them.我尝试使用适用于某些行但并非所有行的 CTE。 Each rain event resets the running totals.每个降雨事件都会重置运行总数。 So each rainy day has its own running total after the last rain event, and doesn't accumulate from previous rainy days.所以每个下雨天在最后一次下雨事件后都有自己的累计,而不是从前一个雨天累积。

I have the column with expected result in this table below.我在下表中有预期结果的列。

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

I tried the below with no success我尝试了以下但没有成功

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

The way that you have described this is rather tricky.您描述的方式相当棘手。 A simpler way is to assign a group to rows based on the number of rainy days that are on or after each row.一种更简单的方法是根据每行上或之后的下雨天数将组分配给行。

Then, each rainy day is in a group with all the preceding non-rainy days.然后,每个下雨天都与之前的所有非下雨天在一个组中。 Just count the size of the group to get the number you want.只需计算组的大小即可获得所需的数字。

In SQL:在 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 is a db<>fiddle. 是一个 db<>fiddle。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM