根据包含多天值的记录创建每日日志

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) &lt; '2020-08-01'

以上是关于根据包含多天值的记录创建每日日志的主要内容,如果未能解决你的问题,请参考以下文章

当 Heroku Papertrail 日志记录达到每日 10 MB 的限制时会发生啥?

根据唯一ID将记录拆分为2个具有不同值的记录

如何在R中提取创建每日首次登机记录

使用外部表加载数据并创建包含拒绝记录的日志文件并说明原因

计算包含特定值的总记录

BigQuery SQL:从日志表创建每日当前状态表