如何解决根据包含多日值的记录创建每日日志
这是此问题的扩展: Break down long multi day periods of time into several single day periods是使用Tallies解决问题的地方。
我现在要处理的情况是,我有一个这样的表:
OutageID ServerOutageStartDateTime OutageLength (hrs)
1 2020/07/05 17:00 12
2 2020/07/15 11:00 3
3 2020/07/15 19:00 2
4 2020/07/22 14:00 72
目标是在一段时间内(例如7月)创建每日停机报告,如下所示:
Date OutageLength (hrs)
2020/07/01 0
2020/07/02 0
2020/07/03 0
2020/07/04 0
2020/07/05 7
2020/07/06 5
2020/07/07 0
...
2020/07/15 5
...
2020/07/22 10
2020/07/23 24
2020/07/24 24
2020/07/22 14
2020/07/23 0
...
谢谢。
P.S 我刚刚看到了另一个问题: Convert Date Range to Individual Days
我将对其进行审核,但在此期间,请随时提供帮助!
解决方法
我们去蛮力将数据分成几个小时。 。 。然后汇总:
with hours as (
select convert(datetime,'2020-07-01') as dteh
union all
select dateadd(hour,1,dteh)
from hours h
where dateadd(hour,dteh) < '2020-08-01'
)
select convert(date,dteh),count(*) as num_hours
from hours h left join
outages o
on o.ServerOutageStartDateTime <= h.dteh and
dateadd(hour,o.OutageLength,o.ServerOutageStartDateTime) > h.dteh
group by convert(date,order by convert(date,dteh)
option (maxrecursion 0);
,
此解决方案还使用计数表。在这种情况下,它使用称为fnTally的理货TVF。
Tally TVF(不带嵌入式注释(请参阅链接))
CREATE FUNCTION [dbo].[fnTally]
(@ZeroOrOne BIT,@MaxN BIGINT)
RETURNS TABLE WITH SCHEMABINDING AS
RETURN WITH
H2(N) AS ( SELECT 1
FROM (VALUES
(1),(1),(1)
)V(N)) --16^2 or 256 rows,H4(N) AS (SELECT 1 FROM H2 a,H2 b) --16^4 or 65,536 rows,H8(N) AS (SELECT 1 FROM H4 a,H4 b) --16^8 or 4,294,967,296 rows
SELECT N = 0 WHERE @ZeroOrOne = 0 UNION ALL
SELECT TOP(@MaxN)
N = ROW_NUMBER() OVER (ORDER BY N)
FROM H8
;
GO
数据
drop table if exists #tTEST;
go
select * INTO #tTEST from (values
(1,cast('2020/07/05 17:00' as datetime),12),(2,'2020/07/15 11:00',3),(3,'2020/07/15 19:00',2),(4,'2020/07/22 14:00',72)) V(OutageID,ServerOutageStartDateTime,OutageLength);
查询
declare @month_dt datetime='2020-07-01';
;with
month_hrs_cte as (
select dateadd(hour,f.N,@month_dt) CalDtm
from fnTally(0,datediff(d,@month_dt,eomonth(@month_dt))*24) f),outage_hrs_cte as (
select OutageID,dateadd(hh,o.ServerOutageStartDateTime) CalDtm
from #tTEST o
cross apply
fnTally(0,o.OutageLength) f)
select convert(date,mhc.CalDtm) CalDt,count(distinct ohc.CalDtm) OutageLength
from month_hrs_cte mhc
left join
outage_hrs_cte ohc on mhc.CalDtm=ohc.CalDtm
group by convert(date,mhc.CalDtm);
结果
CalDt OutageLength
2020-07-01 0
2020-07-02 0
2020-07-03 0
2020-07-04 0
2020-07-05 7
2020-07-06 6
2020-07-07 0
2020-07-08 0
2020-07-09 0
2020-07-10 0
2020-07-11 0
2020-07-12 0
2020-07-13 0
2020-07-14 0
2020-07-15 7
2020-07-16 0
2020-07-17 0
2020-07-18 0
2020-07-19 0
2020-07-20 0
2020-07-21 0
2020-07-22 10
2020-07-23 24
2020-07-24 24
2020-07-25 15
2020-07-26 0
2020-07-27 0
2020-07-28 0
2020-07-29 0
2020-07-30 0
2020-07-31 0
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。