根据包含多天值的记录创建每日日志
Posted
技术标签:
【中文标题】根据包含多天值的记录创建每日日志【英文标题】:Create daily logs based on records that contain multi day values 【发布时间】:2020-09-02 21:36:41 【问题描述】:这是对这个问题的扩展: 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
...
提前致谢。
附言 我刚刚看到另一个问题: Convert Date Range to Individual Days
我将对其进行审查,但与此同时,请随时提供帮助!
【问题讨论】:
请随时向我们展示您的尝试......然后我们可以帮助您。否则我们会为你写完整的东西。 【参考方案1】:此解决方案还使用计数表。在这种情况下,它使用名为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),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)
,(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(1),(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, f.N, 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
【讨论】:
【参考方案2】:让我们使用蛮力将数据分解为几个小时。 . .然后聚合:
with hours as (
select convert(datetime, '2020-07-01') as dteh
union all
select dateadd(hour, 1, dteh)
from hours h
where dateadd(hour, 1, 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, dteh),
order by convert(date, dteh)
option (maxrecursion 0);
【讨论】:
谢谢,我在第 2 行添加了缺少的 ' 并在第 12 行删除了逗号,但它显示:Invalid column name 'dteh'.
在行:select dateadd(hour, 1, dteh)
和 where dateadd(hour, 1, dteh) < '2020-08-01'
以上是关于根据包含多天值的记录创建每日日志的主要内容,如果未能解决你的问题,请参考以下文章