January 13, 2006 at 2:38 am
I have two tables (SQL results) of date-periods, PeriodsPossible and PeriodsUsed, each with a StartDate and EndDate. I want from PeriodsPossible only those records with no dates in PeriodsUsed.
IE (dates as yyyy-mm-dd):
PeriodsUsed
ID StartDate EndDate
A 2006-05-05 2006-05-17
B 2006-05-24 2006-05-24
C 2006-06-01 2006-06-22
PeriodsPossible
ID StartDate EndDate
1 2006-05-01 2006-05-05
2 2006-05-07 2006-05-10
3 2006-05-10 2006-05-20
4 2006-05-20 2006-05-23
5 2006-05-20 2006-05-30
6 2006-07-01 2006-07-29
I want
Not record 1 (2006-05-05 is used)
Not record 2 (2006-05-07 2006-05-10 is used)
Not record 3 (2006-05-10 2006-05-17 is used)
Not record 5 (2006-05-24 is used)
So the only records free are record 4 and 6, these records should be my sql result:
ID StartDate EndDate
4 2006-05-20 2006-05-23
6 2006-07-01 2006-07-29
I don't think that MS SQL Server has a exclusion function. But how could I write a sql clause to realize this?
Or does anyone know a function for this?
January 13, 2006 at 3:11 am
Hi ,
Try this logic..
Select ID, Startdate, EndDate
From PerodPossible PP inner join PeriodUsed PU
on pp.ID != PU.ID and
PP.Startdate not between PU.startdate and PU.Enddate and
PP.EndDate not between PU.startdate and PU.Enddate
Thanks
Shrikant
Regards
Shrikant Kulkarni
January 13, 2006 at 3:28 am
Shrikant,
Why this PP.ID != PU.ID?
I used A,B,C versus 1,2,3 for reason of explanation (for an easy reference). In the real world the table PU (PeriodsUsed) has no ID, it exists of only 2 columns: StartDate and EndDate.
January 13, 2006 at 4:07 am
Try this:
declare @PeriodsUsed table (StartDate datetime, EndDate datetime)
insert @PeriodsUsed select '2006-05-05', '2006-05-17'
insert @PeriodsUsed select '2006-05-24', '2006-05-24'
insert @PeriodsUsed select '2006-06-01', '2006-06-22'
declare @PeriodsPossible table (StartDate datetime, EndDate datetime)
insert @PeriodsPossible select '2006-05-01', '2006-05-05'
insert @PeriodsPossible select '2006-05-07', '2006-05-10'
insert @PeriodsPossible select '2006-05-10', '2006-05-20'
insert @PeriodsPossible select '2006-05-20', '2006-05-23'
insert @PeriodsPossible select '2006-05-20', '2006-05-30'
insert @PeriodsPossible select '2006-07-01', '2006-07-29'
select p.* from @PeriodsPossible p left join @PeriodsUsed u
on
(p.StartDate <= u.StartDate and u.StartDate <= p.EndDate)
or
(u.StartDate <= p.StartDate and p.StartDate <= u.EndDate)
where u.StartDate is null
January 13, 2006 at 4:30 am
Hi
Ohh..Sorry..I haven't seen that part..Anyway Logic Jesper suggested is also good.
Regards
Shrikant Kulkarni
January 13, 2006 at 5:18 am
Jesper,
I had to write it out in a graphical way, to understand the logic of your (superb) solution. But the logic is clear when you see it in front of you. Thank you very much.
What confused me at first, is the IS NULL comparision at the end. But using SELECT * in stead of SELECT p.* made it obvious. Should it be possible without this NULL comparision? By using a WHERE EXISTS clause? I think so.
January 13, 2006 at 5:52 am
You are probably thinking of something like this:
select p.* from @PeriodsPossible p
where not exists
(select * from @PeriodsUsed u
where
(p.StartDate <= u.StartDate and u.StartDate <= p.EndDate)
or
(u.StartDate <= p.StartDate and p.StartDate <= u.EndDate)
)
It is probably only a matter of taste, but I tend to avoid correlated subqueries as I think they are a bit harder to read. There might also be a performance issue, although I am not sure about this...
Added: The logic I use is the following: Two date intervals have common dates if and only if the start date of one of the date intervals is contained in the other date interval.
January 13, 2006 at 6:06 am
I just figured it out myself:
SELECT * FROM @PeriodsPossible P
WHERE NOT EXISTS (SELECT NULL FROM @PeriodsUsed U
WHERE (P.StartDate <= U.Startdate AND U.StartDate <= P.EndDate)
OR (U.StartDate <= P.StartDate AND P.StartDate <= U.EndDate))
But you were faster
Both solutions (JOIN versus EXISTS) give the same Execution plan, so I think it is only a matter of taste.
I'am used to the Exists, so I'll use this one. But the real solution came from you, so again: THANKS!
Viewing 8 posts - 1 through 7 (of 7 total)
You must be logged in to reply to this topic. Login to reply