如何对比行数不同的表中日期列解决SSRS报表打卡匹配问题
解决方案
实现层优先选择
优先在查询层实现该逻辑,SSRS报表层仅做展示和简单样式渲染即可。原因是多对多打卡记录的匹配需要做去重、排序、状态标记,查询层(SQL层面)的集合运算性能远高于报表层的表达式/自定义代码,逻辑也更易维护。
核心问题根源
你当前的关联逻辑是简单的人员+日期+时间差条件关联,两个系统的多条打卡记录会生成笛卡尔积,已经匹配过的记录没有被标记为「已使用」,才会出现重复匹配、误判异常的问题。
具体调整方案
1. 给两侧打卡记录加匹配序号
首先对两个表的打卡记录按人员、打卡日期、打卡类型分组后,按时间升序排序打序号,保证同个人员同一天的第N次上班/下班打卡一一对应:
- 处理Table1:
SELECT badge, clockIn, clockOut, CAST(clockIn AS DATE) AS clockDate, -- 按人员、日期分组,给上班打卡排序打序号 ROW_NUMBER() OVER(PARTITION BY badge, CAST(clockIn AS DATE) ORDER BY clockIn ASC) AS rn_in, ROW_NUMBER() OVER(PARTITION BY badge, CAST(clockIn AS DATE) ORDER BY clockOut ASC) AS rn_out FROM Table1
- 处理Table2:先拆分上下班打卡子集,分别打序号
-- 上班打卡子集 SELECT Badge AS badge, clockTime AS clockIn_t2, CAST(clockTime AS DATE) AS clockDate, ROW_NUMBER() OVER(PARTITION BY Badge, CAST(clockTime AS DATE) ORDER BY clockTime ASC) AS rn_in FROM Table2 WHERE Reason = 'In' -- 下班打卡子集 SELECT Badge AS badge, clockTime AS clockOut_t2, CAST(clockTime AS DATE) AS clockDate, ROW_NUMBER() OVER(PARTITION BY Badge, CAST(clockTime AS DATE) ORDER BY clockTime ASC) AS rn_out FROM Table2 WHERE Reason = 'Out'
2. 调整关联逻辑
关联时除了人员、日期、时间差条件,额外加上序号匹配,避免同一条记录被多次匹配:
SELECT t1.badge, t1.clockIn, t1.clockOut, t2_in.clockIn_t2, t2_out.clockOut_t2, -- 异常标记:匹配不到就是异常 CASE WHEN t2_in.clockIn_t2 IS NULL OR ABS(DATEDIFF(MINUTE, t1.clockIn, t2_in.clockIn_t2)) > 60 THEN '上班打卡异常' WHEN t2_out.clockOut_t2 IS NULL OR ABS(DATEDIFF(MINUTE, t1.clockOut, t2_out.clockOut_t2)) > 60 THEN '下班打卡异常' ELSE '正常' END AS exception_flag FROM 处理后的Table1 t1 LEFT JOIN 处理后的Table2上班子集 t2_in ON t1.badge = t2_in.badge AND t1.clockDate = t2_in.clockDate AND t1.rn_in = t2_in.rn_in AND ABS(DATEDIFF(MINUTE, t1.clockIn, t2_in.clockIn_t2)) <= 60 LEFT JOIN 处理后的Table2下班子集 t2_out ON t1.badge = t2_out.badge AND t1.clockDate = t2_out.clockDate AND t1.rn_out = t2_out.rn_out AND ABS(DATEDIFF(MINUTE, t1.clockOut, t2_out.clockOut_t2)) <= 60
按这个逻辑,你样例中12345的第二条Table2上班打卡(12:41)只会匹配Table1中同序号的第二次上班打卡,不会匹配到第一条Table1的记录,不会出现重复行和误判。
3. 特殊场景兜底(可选)
如果存在跨班次的打卡异常情况(比如某个人漏打一次,后面的打卡序号错位),可以在上述匹配后,再单独把未匹配的记录拿出来做二次模糊匹配,标记为「待核实」即可,避免正常匹配的结果被干扰。
报表层补充说明
如果你的权限仅能修改SSRS报表无法修改查询逻辑,也可以用报表的LookupSet函数+自定义代码实现已匹配记录的标记,但数据量超过1000行就会出现明显卡顿,仅适合小数据量场景使用。
内容的提问来源于stack exchange,提问作者ClandestineTech
相关产品推荐
相关产品推荐

