【问题标题】:打卡/打卡事件之间的日期差/时间跨度
【发布时间】:2022-01-23 05:45:00
【问题描述】:

我们有一个 SQL Server 数据库,该数据库记录某人在多个不同的读卡器上刷身份证的日期和时间,以及其他信息,例如此人的身份证号码、刷卡次数和姓名(位置)等。每次滑动都是在其自己的行上的单独事务。我被要求创建一个报告(最好在 SSRS 中),计算某人何时打卡和何时打卡之间的差异 - 基本上是当他们在两个读卡器之一上打卡时,在两个读卡器之一打卡时。数据库中的相关数据是这样的:

TRANSACK_ID Time TR_SLA TR_DEV_NAME TR_MASTER_ID
41506 2021-12-16 09:18:33.000 03010302 Gate 1 (In) 33
41684 2021-12-16 17:08:32.000 03010303 Gate 1 (Out) 33
41131 2021-12-15 07:10:46.000 03010302 Gate 1 (In) 80
41326 2021-12-15 15:34:58.000 03010303 Gate 1 (In) 80

我要拉取相关数据的查询是:

SELECT TRANSACK_ID, CAST(TRANSACK.TR_DATETIMELOCAL AS datetime) AS Time, TR_SLA, TR_DEV_NAME, TR_MASTER_ID
FROM TRANSACK
where (TRANSACK.TR_SLA = '03010301' OR TRANSACK.TR_SLA = '03010302' OR TRANSACK.TR_SLA = '03010303' OR TRANSACK.TR_SLA = '03010304')
GROUP by TR_MASTER_ID, TRANSACK_ID, TR_DATETIMELOCAL, TR_COMP_NAME, TR_DEV_NAME, TR_SLA
order by TR_MASTER_ID

我可以使用此查询在 SSRS 中填充数据集。我想不通的是如何根据 TR_MASTER_ID 列中的每个 ID 计算每个 Gate 1 (In) 行和 Gate1 (Out) 行之间的时间差。我已经尝试了所有我在 SSRS 中能想到的 datediff 表达式,但没有成功,但可能缺少一些明显的东西。

任何建议或意见将不胜感激。

【问题讨论】:

  • GROUP BY,但没有设置函数。为什么不只选择 DISTINCT?
  • 是实际样本数据还是查询结果?表中不能有重复的列名,并且名为 Time 的列实际上应该包含 times
  • @Stu,抱歉,这是列名中的拼写错误。我用正确的列名修正了错字。
  • 尽管如此,您仍然有两个 TRANSACK_ID
  • @jarlh,感谢您的建议,看来不需要 GROUP BY。

标签: sql sql-server reporting-services


【解决方案1】:

我添加了PunchStatus 来表示员工是否正确打孔。我还评估了“进”的第一拳和“出”的最后一拳作为出拳,以防止多次出拳。如果你愿意,你可以改变那部分。您可以尝试以下方法,查看员工一天中两次打卡之间的间隔时间:

SELECT TR_MASTER_ID,
        PunchDate
        CASE 
           WHEN FirstPunchTime IS NULL THEN 'No Punch In'
           WHEN LastPunchTime IS NULL THEN 'No Punch Out'
           WHEN FirstPunchTime IS NOT NULL AND LastPunchTime IS NOT NULL THEN 'Success'
        END AS PunchStatus,
        CASE 
           WHEN FirstPunchTime IS NOT NULL AND LastPunchTime IS NOT NULL THEN 
                DATEDIFF(second, FirstPunchTime, LastPunchTime) / 3600.0 END AS TimeElapsedInHours
FROM
(SELECT TR_MASTER_ID,
        CAST(CAST(TRANSACK.TR_DATETIMELOCAL AS datetime) AS date) AS PunchDate,
        MIN(CASE WHEN TR_DEV_NAME LIKE '%(In)%' THEN CAST(TRANSACK.TR_DATETIMELOCAL AS datetime) END AS PunchInTime) AS FirstPunchTime,
        MAX(CASE WHEN TR_DEV_NAME LIKE '%(Out)%' THEN CAST(TRANSACK.TR_DATETIMELOCAL AS datetime) END AS PunchInTime) AS LastPunchTime
FROM TRANSACK
GROUP BY TR_MASTER_ID,
        CAST(CAST(TRANSACK.TR_DATETIMELOCAL AS datetime) AS date)) AS T

预期输出:

TR_MASTER_ID PunchDate PunchStatus TimeElapsedInHours
33 2021-12-16 Success 7.8
80 2021-12-15 No Punch Out

【讨论】:

  • 谢谢你的例子。当我在 SSMS 中运行查询时,我收到“'MIN' 不是可识别的内置函数名称”和“'MAX' 不是可识别的内置函数名称”错误。我会尝试进一步解决这些错误。
  • 您使用的是哪个版本的 SSMS?如果您有类似的问题,请查看here
  • 我使用的是 SSMS 版本 18.10。我会看看你提供的链接。
【解决方案2】:

这是我们用来实现目标的方法:

cast( (cast(TR_DATETIMELOCAL as datetime) - lag(TR_DATETIMELOCAL) over (order by TR_MASTER_ID, TR_DATETIMELOCAL)) as time) as diff from TRANSACK

声明在这里找到:Calculate Time Difference Between Two Consecutive Rows

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多