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.
部分城市有雨天或晴天的报告。每个标志值代表一个下雨事件(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.