微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

计算一周中花费的总时间

如何解决计算一周中花费的总时间

我想计算一周中花费的总时间(一周的开始是从给定的日期)。

给定日期为2020-06-23 15:30:00。下周将从7天后开始。

如果只有第二个距距第一个不到一个小时,则活动的持续时间将通过两行相同ID的时间间隔来计算。

select t.UserName,1 + datediff(second,'2020-06-23 15:30:00',CompletedOn) / (24 * 60 * 60 * 7) as week_num,sum(datediff(minute,CompletedOn,next_ts)) as duration_minutes
from (select t.*,lead(CompletedOn) over (partition by UserName order by CompletedOn) as next_ts
from #Results t
where t.CompletedOn >= '2020-06-23 15:30:00'
) t
where datediff(minute,next_ts) < 60 and CompletedOn >='2020-06-23 15:30:00' and t.UserName = 'John B'
group by t.UserName,datediff(second,CompletedOn) / (24 * 60 * 60 * 7)
order by t.UserName,week_num;

上面的查询不考虑显示 week_num ,如果没有星期中的日期条目,则将结果显示为:

   UserName       | week_num |  duration_minutes
   ---------------|----------|------------------
   John B         |    1     |      38
   John B         |    2     |      10
   John B         |    3     |      0
   John B         |    5     |      0

但是,我希望将输出显示为记录中最后一个日期的所有星期数。

   UserName       | week_num |  duration_minutes
   ---------------|----------|------------------
   John B         |    1     |      38
   John B         |    2     |      10
   John B         |    3     |      0
   John B         |    4     |      0
   John B         |    5     |      0

一些示例数据:

       IF OBJECT_ID('tempdb..#Results') IS NOT NULL
        Truncate TABLE #Results
    else
        CREATE TABLE #Results
        (
            UserName varchar(20) not null,CompletedOn datetime not null
        )      
  
   INSERT INTO #Results (UserName,CompletedOn) 
   SELECT 'John B','2020-06-23T15:30:00'
   INSERT INTO #Results (UserName,'2020-06-23T15:31:00'
   --1 min
   
   INSERT INTO #Results (UserName,'2020-06-30T12:57:00'      
   INSERT INTO #Results (UserName,'2020-06-30T13:06:00'
   INSERT INTO #Results (UserName,'2020-06-30T13:34:00'
   --37 min 
   
   
   INSERT INTO #Results (UserName,'2020-06-30 15:31:00'      
   INSERT INTO #Results (UserName,'2020-06-30 15:33:00'
   INSERT INTO #Results (UserName,'2020-06-30 15:41:00'
   
   INSERT INTO #Results (UserName,'2020-07-06 08:41:00'      
   INSERT INTO #Results (UserName,'2020-07-07 14:29:00'
   
   INSERT INTO #Results (UserName,'2020-07-09 15:22:00'      
   INSERT INTO #Results (UserName,'2020-07-09 16:23:00'
   
   INSERT INTO #Results (UserName,'2020-07-21 15:34:00'      
   INSERT INTO #Results (UserName,'2020-07-21 17:00:00'
   
   INSERT INTO #Results (UserName,'2020-07-21 17:00:00'
   INSERT INTO #Results (UserName,'2020-07-23 06:34:00'      
 
   INSERT INTO #Results (UserName,'2020-07-23 08:28:00'
   INSERT INTO #Results (UserName,'2020-07-23 08:28:00'

Db Fiddle

解决方法

考虑加入一个recursive CTE,该匹配会生成UserName和所有后续week_num到定义的端点的配对。下面使用10,但可以扩展为52。

WITH pairs AS (
    SELECT DISTINCT UserName,1 AS week_num
    FROM #Results
    UNION ALL
    SELECT UserName,week_num + 1
    FROM pairs 
    WHERE week_num < 10                 -- ADJUST ## AS NEEDED
),sub AS (
    SELECT t.UserName,t.CompletedOn,LEAD(CompletedOn) OVER (PARTITION BY t.UserName ORDER BY t.CompletedOn) as next_ts
    FROM #Results t
    WHERE t.CompletedOn >= '2020-06-23 15:30:00'
),main AS (
    SELECT sub.UserName,1 + DATEDIFF(SECOND,'2020-06-23 15:30:00',sub.CompletedOn) / (24 * 60 * 60 * 7) AS week_num,SUM(DATEDIFF(MINUTE,sub.CompletedOn,sub.next_ts)) AS duration_minutes
    FROM sub
    WHERE DATEDIFF(MINUTE,sub.next_ts) < 60 
      AND sub.CompletedOn >='2020-06-23 15:30:00' 
      AND sub.UserName = 'John B'
    GROUP BY sub.UserName,DATEDIFF(SECOND,sub.CompletedOn) / (24 * 60 * 60 * 7)
)

SELECT pairs.UserName,pairs.week_num,ISNULL(main.duration_minutes,0) AS duration_minutes
FROM pairs
LEFT JOIN main
   ON pairs.UserName = main.UserName
   AND pairs.week_num = main.week_num

OPTION (MAXRECURSION 0);

Online Demo

|    | UserName | week_num | duration_minutes |
|----|----------|----------|------------------|
| 1  | John B   | 1        | 38               |
| 2  | John B   | 2        | 10               |
| 3  | John B   | 3        | 0                |
| 4  | John B   | 4        | 0                |
| 5  | John B   | 5        | 0                |
| 6  | John B   | 6        | 0                |
| 7  | John B   | 7        | 0                |
| 8  | John B   | 8        | 0                |
| 9  | John B   | 9        | 0                |
| 10 | John B   | 10       | 0                |

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。