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

查找多个滑入/滑出时间戳之间的总分钟数 - 从垂直行中选择多个记录并转换水平行

如何解决查找多个滑入/滑出时间戳之间的总分钟数 - 从垂直行中选择多个记录并转换水平行

我正在处理 sql Server 查询,以获取将处理多个任务代码用户列表的 Badge Out Time - Bade In Time。

task_mgmt - 表名

表格列如下

Task_Sn 用户名 Task_Code 动作 Badge_IN_OUT_TIME
1 安迪 博客 开始 2021-07-20 08:11:45.000
2 安迪 博客 END 2021-07-20 10:11:45.000
3 贝基 ACCTS 开始 2021-07-20 11:11:45.000
4 贝基 ACCTS END 2021-07-20 12:11:45.000
5 安迪 博客 开始 2021-07-20 12:15:45.000
6 安迪 博客 END 2021-07-20 12:25:45.000
7 安迪 博客 开始 2021-07-20 12:25:00.000
8 贝基 ACCTS 开始 2021-07-20 13:00:00.000
9 贝基 ACCTS END 2021-07-20 13:30:00.000

结果除外

用户名 Task_Code Badge_IN_TIME Badge_OUT_TIME TOTAL_MINS_SPENT
安迪 博客 2021-07-20 12:25:55.000 135
贝基 ACCTS 2021-07-20 13:00:00.000 2021-07-20 13:30:00.000 90

我真的想不出对此有任何疑问。我是 sql 的初学者,我知道 CRUD 操作。这对我来说似乎超级复杂。

Select UserName,Task_Code,Badge_In_Time,Badge_Out_Time,(Badge_Out_Time - Badge_In_Time) as TOTAL_TIME_SPENT
from task_mgmt
order by Badge_IN_OUT_TIME desc

由于安迪目前正在进入徽章但尚未退出徽章,因此最新的徽章退出时间戳计算为 [ getdate() - 徽章进入 ] 作为 LastTransaction Mins(5 分钟) )

enter image description here

解决方法

在您的示例数据中,安迪的最后开始时间早于他的最后结束时间,因此造成了重叠。鉴于您如何描述计算总分钟数的逻辑,我假设这是不正确的。因此,在我的示例表中,我进行了相应的调整。

考虑以下事项:

我使用带有 LEAD() 函数的派生表来捕获下一个日期和操作的位置。我在我的外部查询中使用它来根据我的下一步行动来确定使用的分钟数。

我使用交叉申请来确定用户名和任务的最大开始和结束日期。

CREATE TABLE #tmp(Task_Sn int,UserName varchar(20),Task_Code varchar(10),Action varchar(10),Badge_IN_OUT_TIME datetime)
INSERT INTO #tmp
VALUES
(1,'Andy','BLOG','START','2021-07-20 08:11:45.000'),(2,'END','2021-07-20 10:11:45.000'),(3,'Becky','ACCTS','2021-07-20 11:11:45.000'),(4,'2021-07-20 12:11:45.000'),(5,'2021-07-20 12:15:45.000'),(6,'2021-07-20 12:25:45.000'),(7,'2021-07-20 12:35:00.000'),(8,'2021-07-20 13:00:00.000'),(9,'2021-07-20 13:30:00.000')


SELECT X.UserName,X.Task_Code,Y.ST_TIME Badge_IN_TIME,CASE WHEN Y.ST_TIME > Y.ED_TIME THEN NULL ELSE Y.ED_TIME END Badge_OUT_TIME,SUM(CASE WHEN Action = 'START' AND NX_ACTION= 'END' THEN DATEDIFF(minute,Badge_IN_OUT_TIME,NX_TIME) 
         WHEN ACTION = 'START' AND NX_ACTION IS NULL THEN DATEDIFF(minute,GETDATE())
         END) TotalMinutesSpent
FROM(
    select *,LEAD(Badge_IN_OUT_TIME,1) OVER(Partition by UserName,Task_Code  ORDER BY  Badge_IN_OUT_TIME) NX_TIME,LEAD(ACTION,Task_Code ORDER BY  Badge_IN_OUT_TIME) NX_ACTION
    from #tmp
    ) X
CROSS APPLY(SELECT UserName,MAX(CASE WHEN Action = 'START' THEN Badge_IN_OUT_TIME END) ST_TIME,MAX(CASE WHEN Action = 'END' THEN Badge_IN_OUT_TIME END) ED_TIME 
                FROM #tmp t1 
                    WHERE t1.UserName = X.UserName 
                            and t1.Task_Code = X.Task_Code 
                GROUP BY UserName,Task_Code
            ) Y
GROUP BY X.USERNAME,Y.ST_TIME,Y.ED_TIME
,

这似乎有效:

SELECT UserName,Task_Code,task_in.Task_Sn as Task_In_Sn,TOUT.Task_Out_Sn,task_in.Badge_IN_OUT_TIME as Time_In_Raw,FORMAT(task_in.Badge_IN_OUT_TIME,'hh\:mm') as Task_In_Time,FORMAT(TOUT.Task_Out_Time,'hh\:mm') as Task_Out_Time,DATEDIFF(minute,task_in.Badge_IN_OUT_TIME,ISNULL(TOUT.Task_Out_Time,GETDATE())) as LengthOfTime
FROM task_mgmt task_in
    OUTER APPLY (
       SELECT TOP 1
            task_out.Task_Sn as Task_Out_Sn,task_out.Badge_IN_OUT_TIME as Task_Out_Time
        FROM task_mgmt task_out
        WHERE task_out.Action = 'END' AND
              task_out.UserName = task_in.UserName AND
              task_out.Task_Sn > task_in.Task_Sn
        ORDER BY Task_Sn
    ) TOUT
WHERE task_in.Action = 'START'
ORDER BY Task_Sn

请注意,OUTER APPLY 会查找与其他条件匹配的具有较大 Task_Sn 的第一条记录(我可以使用 Badge_IN_OUT_TIME 而不是 Task_Sn,但整数是更好一点,可能更高效)。

还要注意 ISNULL 中的 DATEDIFF,当日期为 GETDATE 时,它会替换 NULL

如果需要对多个区间求和,可以使用GROUP BY

,

我提供了答案,但我知道预期结果中缺少两列。

注意:这两列 Badge_IN_TIME Badge_OUT_TIME 缺失,因为我不确定您要为这两列检索什么,如果您能澄清结果并这些两列的预期值如您为 TOTAL_TIME_SPENT 显示的方式我可以编辑问题并添加这两列推导。

将逻辑添加到上述列后 这是我的查询返回的内容。我认为预期的答案也有一些问题,因为它应该符合逻辑。

SELECT 
  DISTINCT 
  UserName,( SELECT  MAX(Badge_IN_OUT_Time ) from  task_mgmt E where E.UserName =  A.UserName   and A.Task_code =  E.Task_Code and    [Action] ='Start'  )  Badge_IN_TIME,( SELECT  MIN(Badge_IN_OUT_Time ) from  task_mgmt E where E.UserName =  A.UserName   and A.Task_code =  E.Task_Code and    [Action] ='END'  )  Badge_OUT_TIME,SUM( [DATEDIFF] ) OVER (PARTITION BY  UserName,[Action]  order by  UserName ) as  Total_MinsSpend
 FROM 
  (
   SELECT 
   Task_sn,UserName,[Action],Badge_IN_OUT_Time,ISNULL( LEAD(Badge_IN_OUT_Time) over  (Partition by UserName,Task_Code order by UserName ),'2021-07-20 12:30:00.000') as [StartTime_Lead],DATEDIFF ( MINUTE,iSNULL( LEAD(Badge_IN_OUT_Time) over  (Partition by UserName,'2021-07-20 12:30:00.000')  ) as [DATEDIFF] --Get the date dfference  
  FROM  task_mgmt
  )
 AS A Where A.[Action]  in ('Start')

Result

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