Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
| Author |
Topic |
|
rokhri
Starting Member
10 Posts |
Posted - 2011-04-28 : 05:57:40
|
| I have following two tables. I want to search all records from Table1 where datetime is not available for Table2 recordsCREATE TABLE #Table1 (StartDate DATETIME, EndDate DATETIME)INSERT INTO #Table1SELECT '2011/03/01 08:01','2011/03/01 11:00'UNION ALLSELECT '2011/03/01 13:01','2011/03/01 16:00'UNION ALLSELECT '2011/03/01 18:01','2011/03/01 23:59'CREATE TABLE #Table2 (TStartDate DATETIME, TEndDate DATETIME)INSERT INTO #Table2SELECT '2011/03/01 06:00', '2011/03/01 11:00'UNION ALLSELECT '2011/03/01 19:00',' 2011/03/01 22:00'UNION ALLSELECT '2011/03/01 10:00','2011/03/01 13:30'--REQUIRED OUTPUTStartDate,EndDate'2011/03/01 06:00', '2011/03/01 08:00''2011/03/01 11:01', '2011/03/01 13:00' |
|
|
nigelrivett
Master Smack Fu Yak Hacker
3385 Posts |
Posted - 2011-04-28 : 06:29:34
|
| I can see why the first row is there - tyhe first row in t2 is not covered by the t1 row.I don't understand the second though - it seems to be from the end of the first row in t1 to the start of the 2nd but there is no coresponding entry in t2.==========================================Cursors are useful if you don't know sql.SSIS can be used in a similar way.Beer is not cold and it isn't fizzy. |
 |
|
|
rokhri
Starting Member
10 Posts |
Posted - 2011-04-28 : 06:33:36
|
| second row is also not convered by t1 from 11:01 to 13:00 |
 |
|
|
Seventhnight
Master Smack Fu Yak Hacker
2878 Posts |
Posted - 2011-04-28 : 06:35:20
|
quote: Originally posted by rokhri second row is also not convered by t1 from 11:01 to 13:00
Right... but its not part of Table1 either...Corey I Has Returned!! |
 |
|
|
nigelrivett
Master Smack Fu Yak Hacker
3385 Posts |
Posted - 2011-04-28 : 06:39:59
|
| It's not within the start and end dates of either table.==========================================Cursors are useful if you don't know sql.SSIS can be used in a similar way.Beer is not cold and it isn't fizzy. |
 |
|
|
rokhri
Starting Member
10 Posts |
Posted - 2011-04-28 : 06:42:08
|
| yeah both required output rows are not part of table1.1- for first record of table2, only partial time is missing that is 6:00 to 8:002- for second row of table2 time is from 19:00 to 22:00 which is already being covered by table1 so NOT a part of output3- for third row of table 2 there is no record or records in table1 which cover from 11:01 to 13:00, though from 10:00 to 11:00 it is being covered by first row of t1 and from 3:00 to 3:30 covered by by second row of t1 but time 11:01 to 13:00 is missingi need that un-overlapping time |
 |
|
|
nigelrivett
Master Smack Fu Yak Hacker
3385 Posts |
Posted - 2011-04-28 : 06:51:54
|
| Sorry - thought your data was in order - didn't realise it was overlapping.==========================================Cursors are useful if you don't know sql.SSIS can be used in a similar way.Beer is not cold and it isn't fizzy. |
 |
|
|
rokhri
Starting Member
10 Posts |
Posted - 2011-04-28 : 07:06:20
|
| any idea ??? |
 |
|
|
nigelrivett
Master Smack Fu Yak Hacker
3385 Posts |
Posted - 2011-04-28 : 07:09:08
|
| It's probably not easy.My approach would be to first merge the rows into continuous time periods - which would be easier with a loop then find the missing bits.Another option would be to convert to minute intervals for both tables then find the consecutive periods that are missing - that would probably be the easiest to code.==========================================Cursors are useful if you don't know sql.SSIS can be used in a similar way.Beer is not cold and it isn't fizzy. |
 |
|
|
rokhri
Starting Member
10 Posts |
Posted - 2011-04-28 : 07:12:45
|
| loop is a poor approach and it will slow down my query at production. I want somthing like followinghttp://stackoverflow.com/questions/2186730/tsql-datetime-overlapping-and-interval-values |
 |
|
|
Seventhnight
Master Smack Fu Yak Hacker
2878 Posts |
Posted - 2011-04-28 : 07:28:57
|
The records in the second table overlapping seem to cause some confusion... but I suppose they could be collapsed, if I was less lazy.Declare @t1 Table ( tStart datetime, tEnd datetime)INSERT INTO @t1SELECT '2011/03/01 08:01','2011/03/01 11:00'UNION ALLSELECT '2011/03/01 13:01','2011/03/01 16:00'UNION ALLSELECT '2011/03/01 18:01','2011/03/01 23:59'Declare @t2 Table ( tStart datetime, tEnd datetime)/*INSERT INTO @t2SELECT '2011/03/01 06:00', '2011/03/01 11:00' UNION ALLSELECT '2011/03/01 19:00',' 2011/03/01 22:00'UNION ALLSELECT '2011/03/01 10:00','2011/03/01 13:30' -- Overlaps with 6-11 record??*/INSERT INTO @t2SELECT '2011/03/01 06:00', '2011/03/01 10:00' UNION ALLSELECT '2011/03/01 19:00',' 2011/03/01 22:00'UNION ALLSELECT '2011/03/01 10:00','2011/03/01 13:30' ;with z As ( Select dy = dateadd(dy,datediff(dy,0,tStart),0), tStart, tEnd, r = Row_Number() Over(Partition By dateadd(dy,datediff(dy,0,tStart),0) Order By tStart) From @t1 A), y As ( Select *, r = Row_Number() Over(Partition By dateadd(dy,datediff(dy,0,tStart),0) Order By tStart) From ( Select dy = isnull(A.dy,B.dy), tStart = isnull(A.tStart,isnull(A.dy,B.dy)), tEnd = isnull(A.tEnd,B.tStart), InT1 = case when A.tStart is not null then 1 else 0 end From z A Full Join z B On A.r = B.r-1 Union All Select dy = A.dy, tStart = A.tEnd, tEnd = isnull(B.tStart,dateadd(minute,-1,A.dy+1)), InT1 = 0 From z A Left Join z B On A.r = B.r-1 ) C Where tStart <> tEnd), xAs ( Select dy = dateadd(dy,datediff(dy,0,tStart),0), tStart, tEnd, r = Row_Number() Over(Partition By dateadd(dy,datediff(dy,0,tStart),0) Order By tStart) From @t2 A), w As ( Select *, r = Row_Number() Over(Partition By dateadd(dy,datediff(dy,0,tStart),0) Order By tStart) From ( Select dy = isnull(A.dy,B.dy), tStart = isnull(A.tStart,isnull(A.dy,B.dy)), tEnd = isnull(A.tEnd,B.tStart), InT2 = case when A.tStart is not null then 1 else 0 end From x A Full Join x B On A.r = B.r-1 Union All Select dy = A.dy, tStart = A.tEnd, tEnd = isnull(B.tStart,dateadd(minute,-1,A.dy+1)), InT2 = 0 From x A Left Join x B On A.r = B.r-1 ) C Where tStart <> tEnd), cteAs ( Select a.dy, --C.n, tStart = case C.n when 1 then case when A.tStart < B.tStart then A.tStart else B.tStart end when 2 then case when A.tStart < B.tStart then B.tStart else A.tStart end when 3 then case when A.tEnd < B.tEnd then A.tEnd else B.tEnd end end, tEnd = case C.n when 1 then case when A.tStart < B.tStart then B.tStart else A.tStart end when 2 then case when A.tEnd < B.tEnd then A.tEnd else B.tEnd end when 3 then case when A.tEnd < B.tEnd then B.tEnd else A.tEnd end end, InT1 = case C.n when 1 then case when A.tStart < B.tStart then A.InT1 else 0 end when 2 then A.InT1 when 3 then case when A.tStart < B.tStart then 0 else A.InT1 end end, InT2 = case C.n when 1 then case when A.tStart < B.tStart then 0 else B.InT2 end when 2 then B.InT2 when 3 then case when A.tStart < B.tStart then B.InT2 else 0 end end, tStart1 = A.tStart, tEnd1 = A.tEnd, T1 = A.InT1, tStart2 = B.tStart, tEnd2 = B.tEnd, T2 = B.InT2, r = Row_Number() Over (Partition By A.dy Order By A.r, B.r, C.n) From y A Left Join w B On A.tStart <= B.tEnd and A.tEnd > B.tStart Cross Join (Select n=1 Union Select n=2 Union Select n=3) C)Select dy, tStart, tEnd, InT1 = max(InT1), InT2 = max(InT2)From cte Where tStart <> tEndgroup by dy, tStart, tEndHaving max(InT2) = 0Order By 1, 2 Corey I Has Returned!! |
 |
|
|
nigelrivett
Master Smack Fu Yak Hacker
3385 Posts |
Posted - 2011-04-28 : 07:30:36
|
| maybe ;with cte21 as (select startdate = MIN(TStartDate), enddate = MAX(TEndDate) from #Table2), cte22 as(select tme = startdate from cte21union allselect DATEADD(mi,1,tme) from cte22 where tme < (select enddate from cte21)),cte23 as (select * from cte22 where exists (select * from #Table2 where tme between TStartDate and TEndDate)),cte as (select tme from cte23 where not exists (select * from #Table1 where tme between StartDate and EndDate)) -- gaps,ctea as (select *, seq = ROW_NUMBER() over (order by tme) from cte c1 where not exists (select * from cte c2 where DATEADD(mi,1,c2.tme) = c1.tme)),cteb as (select *, seq = ROW_NUMBER() over (order by tme) from cte c1 where not exists (select * from cte c2 where DATEADD(mi,1,c1.tme) = c2.tme))select startdate = ctea.tme, enddate = cteb.tme from cteajoin cteb on ctea.seq = cteb.seqoption (maxrecursion 0)==========================================Cursors are useful if you don't know sql.SSIS can be used in a similar way.Beer is not cold and it isn't fizzy. |
 |
|
|
Seventhnight
Master Smack Fu Yak Hacker
2878 Posts |
Posted - 2011-04-28 : 07:32:59
|
This is much shorter... I didn't test it though  quote: Originally posted by nigelrivett maybe ;with cte21 as (select startdate = MIN(TStartDate), enddate = MAX(TEndDate) from #Table2), cte22 as(select tme = startdate from cte21union allselect DATEADD(mi,1,tme) from cte22 where tme < (select enddate from cte21)),cte23 as (select * from cte22 where exists (select * from #Table2 where tme between TStartDate and TEndDate)),cte as (select tme from cte23 where not exists (select * from #Table1 where tme between StartDate and EndDate)) -- gaps,ctea as (select *, seq = ROW_NUMBER() over (order by tme) from cte c1 where not exists (select * from cte c2 where DATEADD(mi,1,c2.tme) = c1.tme)),cteb as (select *, seq = ROW_NUMBER() over (order by tme) from cte c1 where not exists (select * from cte c2 where DATEADD(mi,1,c1.tme) = c2.tme))select startdate = ctea.tme, enddate = cteb.tme from cteajoin cteb on ctea.seq = cteb.seqoption (maxrecursion 0)==========================================Cursors are useful if you don't know sql.SSIS can be used in a similar way.Beer is not cold and it isn't fizzy.
Corey I Has Returned!! |
 |
|
|
nigelrivett
Master Smack Fu Yak Hacker
3385 Posts |
Posted - 2011-04-28 : 07:36:21
|
| But it transforms into minute intervals. If the time intervals are large I would consider using temp tables so that it could be indexed. Doing this sort of thing can be surprisingly quick but you have to be careful with it.People tend to find this easier to understand rather than having to deal with starts and ends of periods and the various conditions that can occur.==========================================Cursors are useful if you don't know sql.SSIS can be used in a similar way.Beer is not cold and it isn't fizzy. |
 |
|
|
rokhri
Starting Member
10 Posts |
Posted - 2011-04-28 : 07:40:34
|
| wow....nigelrivettThanx buddythanx Seventhnight(Thats the reason i left ORACLE, SQL Server community is much more helpful) |
 |
|
|
rokhri
Starting Member
10 Posts |
Posted - 2011-04-28 : 07:42:40
|
| nigelrivetti need ur permission to publish this solution through my blog |
 |
|
|
Seventhnight
Master Smack Fu Yak Hacker
2878 Posts |
Posted - 2011-04-28 : 07:45:48
|
Yeah... it will take a little dissecting for me to wrap my head around this, but hey, that's the whole point Corey I Has Returned!! |
 |
|
|
nigelrivett
Master Smack Fu Yak Hacker
3385 Posts |
Posted - 2011-04-28 : 07:52:20
|
quote: Originally posted by rokhri nigelrivetti need ur permission to publish this solution through my blog
Go ahead - mention me as I may turn this into an article at some point together with the other dozen+ that are waiting to be sent for publishing.==========================================Cursors are useful if you don't know sql.SSIS can be used in a similar way.Beer is not cold and it isn't fizzy. |
 |
|
|
nigelrivett
Master Smack Fu Yak Hacker
3385 Posts |
Posted - 2011-04-28 : 08:03:34
|
| Here's a version with a few coments-- limits of period - first start date, last end date;with cte21 as (select startdate = MIN(TStartDate), enddate = MAX(TEndDate) from #Table2)-- table of minutes bewteen start and end dates, cte22 as(select tme = startdate from cte21union allselect DATEADD(mi,1,tme) from cte22 where tme < (select enddate from cte21))-- minutes that are included in #Table2 periods,cte23 as (select * from cte22 where exists (select * from #Table2 where tme between TStartDate and TEndDate))-- minutes that are not covered by #Table1 periods,cte as (select tme from cte23 where not exists (select * from #Table1 where tme between StartDate and EndDate)) -- gaps-- Start dates of periods not covered,ctea as (select *, seq = ROW_NUMBER() over (order by tme) from cte c1 where not exists (select * from cte c2 where DATEADD(mi,1,c2.tme) = c1.tme))-- end dates of periods not covered,cteb as (select *, seq = ROW_NUMBER() over (order by tme) from cte c1 where not exists (select * from cte c2 where DATEADD(mi,1,c1.tme) = c2.tme))-- start and end dates of periods not coveredselect startdate = ctea.tme, enddate = cteb.tme from cteajoin cteb on ctea.seq = cteb.seqoption (maxrecursion 0)==========================================Cursors are useful if you don't know sql.SSIS can be used in a similar way.Beer is not cold and it isn't fizzy. |
 |
|
|
Seventhnight
Master Smack Fu Yak Hacker
2878 Posts |
Posted - 2011-04-28 : 08:25:44
|
Thanks! Saves me some trouble  quote: Originally posted by nigelrivett Here's a version with a few coments...
Corey I Has Returned!! |
 |
|
|
|
|
|
|
|