【问题标题】:SQL Calculate Consecutive hours [closed]SQL计算连续时间[关闭]
【发布时间】:2020-07-07 03:44:51
【问题描述】:

需要计算连续小时数。

这是数据

╔════╦══════════╦════════════╦═══════════╦═══════╗
║ ID ║ ClientID ║ Date       ║ From(Min) ║ To    ║  
╠════╬══════════╬════════════╬═══════════╬═══════╣
║ 101║ 2563     ║ 2020-06-19 ║ 360       ║ 1080  ║  
║ 102║ 2563     ║ 2020-06-19 ║ 1080      ║ 1140  ║ 
║ 103║ 2563     ║ 2020-06-19 ║ 1140      ║ 1200  ║  
║ 104║ 2561     ║ 2020-06-19 ║ 360       ║ 1080  ║  
║ 105║ 2563     ║ 2020-06-19 ║ 1200      ║ 1440  ║  
║ 106║ 2563     ║ 2020-06-20 ║ 0         ║ 60    ║  
║ 107║ 2561     ║ 2020-05-19 ║ 1080      ║ 1140  ║ 
║ 107║ 2563     ║ 2020-05-20 ║ 1080      ║ 1140  ║ 
╚════╩══════════╩════════════╩═══════════╩═══════╝

这个客户端有一个允许的连续小时数的限制。

这是我正在寻找的结果

╔══════════╦════════════╦═════════╦═════════╦═══════╦═══════════════════╗
║ ClientID ║ Date       ║ From    ║ To      ║ Hours ║ Consecutive Hours ║
╠══════════╬════════════╬═════════╬═════════╬═══════╣═══════════════════╣
║ 2563     ║ 2020-06-19 ║ 6:00am  ║ 6:00pm  ║ 12    ║ 12                ║
║ 2563     ║ 2020-06-19 ║ 6:00pm  ║ 7:00pm  ║ 1     ║ 13                ║
║ 2563     ║ 2020-06-19 ║ 7:00pm  ║ 8:00pm  ║ 1     ║ 14                ║
║ 2563     ║ 2020-06-19 ║ 8:00pm  ║ 12:00am ║ 4     ║ 18                ║
║ 2563     ║ 2020-06-20 ║ 12:00am ║ 1:00am  ║ 1     ║ 19                ║
║ 2563     ║ 2020-06-20 ║ 6:00pm  ║ 7:00pm  ║ 1     ║ 1                 ║
║ 2561     ║ 2020-06-19 ║ 6:00am  ║ 6:00pm  ║ 12    ║ 12                ║
║ 2561     ║ 2020-06-19 ║ 7:00pm  ║ 8:00pm  ║ 1     ║ 13                ║
╚══════════╩════════════╩═════════╩═════════╩═══════╩═══════════════════╝

或计算客户是否超过允许的连续小时数的公式。

【问题讨论】:

  • 你试过什么?你在哪里卡住了?
  • 这很快@DaleK,将发布我明天(下班)的内容。谢谢
  • 允许的最大连续小时数是多少?
  • 请确认样本数据中是否有拼写错误。源数据的日期是 2018 年,但结果只有 2020 年。另外,您使用什么版本的 SQL Sever?请标记版本。
  • @monsey11,总的来说,这看起来像是一个 Packing Intervals 问题,Itzik Ben-Gan 在他的文章中详细讨论了这个问题。他还在那里展示了如何忽略不超过一定长度的间隙。

标签: sql aggregate recursive-query sql-server-2017 gaps-and-islands


【解决方案1】:

这是一种孤岛问题。因为您正在处理分钟,所以对我来说,累积分钟而不是小时更有意义。你可以除以 60 得到小时数:

select t.*,
       sum(tom - fromm) over (partition by clientid, date, grp order by fromm) as consecutive_minutes
from (select t.*,
             sum(case when prev_tom = fromm then 0 else 1 end) over (partition by clientid, date order by fromm) as grp
      from (select t.*,
                   dateadd(minute, fromm, date) as fromdt,
                   dateadd(minute, tom, date) as todt,
                   lag(tom) over (partition by clientid, date order by fromm) as prev_tom
            from t
          ) t
     ) t
order by clientid, date, fromm;

编辑:

要处理数天的小时数实际上只是调整上面的查询:

select t.*,
       sum(tom - fromm) over (partition by clientid, grp order by date, fromm) as consecutive_minutes
from (select t.*,
             sum(case when prev_todt = fromdt then 0 else 1 end) over (partition by clientid order by date, fromm) as grp
      from (select t.*,
                   dateadd(minute, fromm, date) as fromdt,
                   dateadd(minute, tom, date) as todt,
                   lag(dateadd(minute, tom, date)) over (partition by clientid order by date, fromm) as prev_todt
            from t
          ) t
     ) t
order by clientid, date, fromm;

Here 是一个 dbfiddle。

【讨论】:

  • 只在同一日期内计算。如果小时重叠超过一天。
  • 如果小时重叠超过一天,它不会将其添加到 Continuous_minutes。日期:7/7/20 汤姆:1440 真正意味着 7/8/20 12am
  • 日期字段是日期数据类型而不是日期时间。需要为 DATEADD 函数转换为日期时间。
  • @monsey11。 . .相同的基本查询可以进行一些调整。
  • 像魅力一样工作。谢谢你。将设置为答案。想知道是否有更好的性能选择。用户在输入日期和时间时会收到提示。还需要检查大型数据集的能力。这只是它检查的许多其他验证的一部分,因此速度尤为重要。
猜你喜欢
  • 1970-01-01
  • 2016-01-18
  • 2021-06-11
  • 2017-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多