Sql server 如何在T-SQL/MSSQL中再次通过数据进行CTE搜索?
目前,我有一个员工时间条目列表,如下所示:Sql server 如何在T-SQL/MSSQL中再次通过数据进行CTE搜索?,sql-server,tsql,common-table-expression,recursive-query,gaps-and-islands,Sql Server,Tsql,Common Table Expression,Recursive Query,Gaps And Islands,目前,我有一个员工时间条目列表,如下所示: TimeSheetId TechnicianUserId TimeSheetDate FromDatetime ToDatetime 1215286 4730 2020-11-10 2020-11-10 14:15:00.000 2020-11-10 15:15:00.000 1215965 4730 2020-11
TimeSheetId TechnicianUserId TimeSheetDate FromDatetime ToDatetime
1215286 4730 2020-11-10 2020-11-10 14:15:00.000 2020-11-10 15:15:00.000
1215965 4730 2020-11-10 2020-11-10 15:15:00.000 2020-11-10 15:45:00.000
1215969 4730 2020-11-10 2020-11-10 15:45:00.000 2020-11-10 17:45:00.000
1215972 4730 2020-11-10 2020-11-10 17:45:00.000 2020-11-10 23:45:00.000
1215967 4730 2020-11-10 2020-11-10 23:45:00.000 2020-11-10 23:59:00.000
1215968 4730 2020-11-11 2020-11-11 00:00:00.000 2020-11-11 00:15:00.000
1215978 4730 2020-11-11 2020-11-11 00:15:00.000 2020-11-11 00:30:00.000
1215980 4730 2020-11-11 2020-11-11 16:00:00.000 2020-11-11 16:30:00.000
1215979 4735 2020-11-11 2020-11-11 00:30:00.000 2020-11-11 08:30:00.000
由于我们的时间是如何处理的,我希望第6行和第7行的时间表日期回滚一天,因为从技术上讲,它与前面的行是连续的时间,并且由我们的系统处理,因为所有的时间都发生在11月10日,而不是11月11日。不应在第7行或第9行不同员工编号之后立即回滚第8行
当我尝试嵌套查询时,我只捕获第6行。当我尝试一个没有时间表的CTE时,因为我不知道如何实现一种依赖它的方法,它不知道什么时候停止迭代并抛出。我如何确保我同时赶上第6行和第7行
我尝试过的CTE:
;WITH CTEDummyData (
[TechnicianUserId]
,[TimeSheetDate]
,[FromDatetime]
,[ToDatetime]
)
AS (
SELECT [TechnicianUserId]
,[TimeSheetDate]
,[FromDatetime]
,[ToDatetime]
FROM @DummyTime
UNION ALL
SELECT [TechnicianUserId]
,CASE
WHEN DATEDIFF(MINUTE,LAG([ToDateTime]) OVER (ORDER BY [FromDatetime]),[FromDatetime]) < 2
AND CAST([FromDatetime] AS DATE) <> LAG([TimeSheetDate]) OVER (ORDER BY [FromDatetime])
THEN DATEADD(DAY,-1,[TimeSheetDate])
ELSE [TimeSheetDate]
END
,[FromDatetime]
,[ToDatetime]
FROM CTEDummyData
)
SELECT *
FROM CTEDummyData
OPTION (MAXRECURSION 24)
我尝试了一个使用SQL循环的解决方案,在迭代中更新数据,直到它完全符合您的需要
DECLARE @NOMOREFORMATTINGNEEDED AS BIT = 0;
IF (EXISTS(SELECT * FROM SYS.tables WHERE name like '%TempDummyTimeTable%'))
BEGIN
Drop table #TempDummyTimeTable;
END
SELECT * INTO #TempDummyTimeTable FROM DummyTimeTable;
WHILE (@NOMOREFORMATTINGNEEDED = 0)
BEGIN
update tl set TimeSheetDate = t.TimeSheetDate from #TempDummyTimeTable tl
join #TempDummyTimeTable t on tl.TechnicianUserId = t.technicianuserid
and ABS(DATEDIFF (MINUTE, tl.FromDatetime, t.ToDatetime)) <= 1
and tl.TimeSheetDate <> t.TimeSheetDate
IF (not exists(select * from #TempDummyTimeTable tl JOIN #TempDummyTimeTable t on tl.TechnicianUserId = t.technicianuserid
and ABS(DATEDIFF (MINUTE, tl.FromDatetime, t.ToDatetime)) <= 1
and tl.TimeSheetDate <> t.TimeSheetDate ) )
BEGIN
SET @NOMOREFORMATTINGNEEDED = 1
END
END
select * from #TempDummyTimeTable
基本上,您可以在原始表的基础上创建一个新的临时表。
然后检查是否有任何行的实例与同一员工的另一行连续,但具有不同的时间表日期,然后更新该行的时间表日期。
在循环中继续执行此操作,直到@nomoreformatingneeded标志设置为true。将此标志设置为true的是一项检查,用于验证不再存在具有不同时间表日期的连续记录。我检查了一个的FromDateTime是否在另一个的ToDateTime的一分钟之内。
让我知道,如果这对你有用。< / P>只需双检查,行5和6被分类为连续的,尽管它们之间有一个完整的分钟,不像其他的结束和开始在同一时间。要添加到戴夫的评论,需要多少差距需要考虑2行附近作为不同的日期?您当前的系统/数据是否精确到最近的分钟?午夜是否有特殊处理,但您需要验证?有点奇怪,几乎所有行的时间都正好落在15分钟的边界上。@iamdave-由于午夜/白天的变化,系统强制执行这一分钟的差异。对于所有其他目的,应将其视为连续的。@SMor-是的,数据精确到最接近的分钟。技术人员使用的GUI将时间强制到最接近的分钟,并且时间通常为15秒,这就是数据看起来像这样的原因。如上所述,系统强制在晚上11:59到午夜之间留出一分钟来区分日历日。否则,时间被认为是连续的。顺便说一句,那一分钟的休息?我将创建一个视图,强制在下一个日期的23:59:00到00:00:00之间执行任何操作,这将修复UI条目的奇怪之处,并且应该为您的实际逻辑提供一个更理智的基础…这非常有效!非常感谢你!