SQL视图中如何将同ID行的TASDateTimeStart设为上一行TASDateTimeEnd?
解决方案
以下是实现需求的修正代码,解决了子查询报错问题,同时实现了同一Id分组内当前行TASDateTimeStart继承上一行TASDateTimeEnd的逻辑:
WITH SplitData AS ( SELECT eci.Id, eci.Employee, eci.JobType, ei.EmployeeName, ei.EmployeeNumber, ss.value AS SerialNumber, -- 保留原始时间字段用于后续计算 CAST(eci.TASDateTimeEnd AS smalldatetime) OriginalEndTime, CAST(eci.TASDateTimeStart AS smalldatetime) OriginalStartTime, -- 计算拆分后单条记录的时长,移除冗余子查询 ISNULL( DATEDIFF(MINUTE, eci.TASDateTimeStart, eci.TASDateTimeEnd) / (LEN(eci.SerialNo) - LEN(REPLACE(eci.SerialNo, ',', '')) + 1), DATEDIFF(MINUTE, eci.TASDateTimeStart, CURRENT_TIMESTAMP) / (LEN(eci.SerialNo) - LEN(REPLACE(eci.SerialNo, ',', '')) + 1) ) AS MinutesClocked, ei.Department, ei.DepartmentNumber, -- 生成分组内行号用于排序(SQL Server 2022+ 可替换为 ss.ordinal 保证拆分顺序) ROW_NUMBER() OVER (PARTITION BY eci.Id ORDER BY (SELECT NULL)) AS RowNum FROM MallaghanApp.dbo.EmployeeClockIn eci CROSS APPLY STRING_SPLIT(eci.SerialNo, ',') ss LEFT JOIN MallaghanApp.dbo.EmployeeInfo ei ON eci.Employee = ei.EmployeeCombinedInfo ) SELECT Id, Employee, JobType, EmployeeName, EmployeeNumber, SerialNumber, OriginalEndTime AS TASDateTimeEnd, -- 第一行用原始开始时间,后续行继承上一行的结束时间 COALESCE(LAG(OriginalEndTime) OVER (PARTITION BY Id ORDER BY RowNum), OriginalStartTime) AS TASDateTimeStart, MinutesClocked, Department, DepartmentNumber FROM SplitData;
关键修改说明
- 修复子查询报错:原代码中嵌套的
(SELECT DATEDIFF(...))属于冗余写法,直接移除外层SELECT即可,避免因子查询返回多行引发的错误。 - 实现时间连续逻辑:通过CTE拆分数据并生成分组内行号,使用
LAG()窗口函数获取同一Id分组内上一行的TASDateTimeEnd值,第一行通过COALESCE回退到原始开始时间。 - 优化代码可读性:给表添加别名简化结构,拆分复杂计算逻辑,避免重复转换和计算。
内容的提问来源于stack exchange,提问作者Breandan McCann
相关产品推荐
相关产品推荐

