2014-02-21 6 views
5

CTE gibt einen unten ErgebnisIgnorieren aktuelle Liste von CTE

Name   | StartDateTime   | EndDateTime   
--------------------+-------------------------+------------------------ 
Hair Massage  | 2014-02-15 09:00:00.000 | 2014-02-15 10:00:00.000 
Hair Massage  | 2014-02-15 10:00:00.000 | 2014-02-15 11:00:00.000 
(X)Hair Massage  | 2014-02-23 09:00:00.000 | 2014-02-23 10:00:00.000 
(X)Hair Cut   | 2014-02-20 12:15:00.000 | 2014-02-20 13:00:00.000 
Hair Cut   | 2014-03-07 11:30:00.000 | 2014-03-07 12:15:00.000 

Auch habe ich Urlaub

Id  | StartDateTime  | EndDateTime   
-------------+--------------------+------------------- 
    1  | 20140223 00:00:00 | 20140224 23:59:00 

Und EventBooking

EventId | StartDateTime   | EndDateTime   
-------------+-------------------------+------------------------ 
    1  | 2014-02-20 12:15:00.000 | 2014-02-20 13:00:00.000 

Ich möchte die Daten entfernen fällt unter holidays and EventBooking von meinem CTE. Ich meine die (X) recods von meinem CTE ist mein

RESULT=CTE- BookedSchedule-Holidays

with HoliDaysCte2 as 
(
select StartdateTime,EndDateTime from Holidays 
union all 
select StartdateTime,EndDateTime from EventBooking 
) 

SELECT 
    Name, 
    StartDateTime, 
    EndDateTime 

FROM CTE WHERE not exists (select 1 
       from HoliDaysCte2 h 
       where cast(a.RepeatEventDate as DATETIME) between 
        cast(h.startdatetime as DATETIME) 
        and cast(h.enddatetime as DATETIME) 
       ) 

Hier entfernen SQL FIDDLE DEMO

+0

Da Sie in Ihrem Design keine Kalendereinheit haben, ist es unvermeidlich, dass Abfragen mit Table-Scans das gewünschte Ergebnis liefern. BTW Aktuelle Tabellen müssen auf Datumsfeldern zusammengefügt werden, das bedeutet eine nicht effektive, aber effiziente Lösung. –

+0

Haben Sie meine Anfrage versucht? Es gibt genau das zurück, was Sie wollen. – dnoeth

Antwort

4

Ok Angenommen, dies ist Ihr Schema

CREATE TABLE dbo.StaffSchedule 
(  ID INT IDENTITY(1, 1) NOT NULL, 
     Name Varchar(50),  
     StartdateTime DATETIME2 NOT NULL, 
     EndDateTime DATETIME2 NOT NULL 
); 

CREATE TABLE dbo.BookedSchedules 
(  ID INT IDENTITY(1, 1) NOT NULL, 
     StaffId INT,   
     StartdateTime DATETIME2 NOT NULL, 
     EndDateTime DATETIME2 NOT NULL 
); 


CREATE TABLE dbo.Holidays 
(  ID INT, 
     StartdateTime DATETIME2 NOT NULL, 
     EndDateTime DATETIME2 NOT NULL 
); 
INSERT dbo.StaffSchedule (Name, StartdateTime, EndDateTime) 
VALUES 
    ('Hair Massage','2014-02-15 09:00:00.000','2014-02-15 10:00:00.000'), 
    ('Hair Massage','2014-02-15 10:00:00.000','2014-02-15 11:00:00.000'), 
    ('(X)Hair Massage','2014-02-23 09:00:00.000','2014-02-23 10:00:00.000'), 
    ('(X)Hair Cut','2014-02-20 12:15:00.000','2014-02-20 13:00:00.000'), 
    ('Hair Cut','2014-03-07 11:30:00.000','2014-03-07 12:15:00.000'); 


INSERT dbo.BookedSchedules (StaffId, StartdateTime, EndDateTime) 
VALUES 
(1,'2014-02-20 12:15:00.000','2014-02-20 13:00:00.000'); 

INSERT dbo.Holidays (ID,StartdateTime, EndDateTime) 
VALUES 
(1,'20140223 00:00:00','20140224 23:59:00'); 

Ist das Ihr Problem löst?

select * from StaffSchedule SS 
where 
not exists(
select * from NonBookingSlots NBS 
where (dateadd(MICROSECOND,1,ss.StartdateTime) 
    between nbs.StartdateTime and nbs.EndDateTime) 
     or (dateadd(MICROSECOND,-1,ss.EndDateTime) 
    between nbs.StartdateTime and nbs.EndDateTime)) 
+0

Der Datensatz "Id = 2" fehlt. Zeigt nur einen Datensatz an. CHeck this http://sqlfiddle.com/#!/0/07698/46 – Billa

+0

Um Bindungen zu vermeiden, können Sie nicht einfach eine Millisekunde zu den Randwerten hinzufügen? select * from StaffSchedule SS wo existiert nicht (1 wählen aus NonBookingSlots BS wobei (ss.StartdateTime \t \t \t \t \t \t zwischen dateadd (Millisekunden, 1, bs.StartdateTime) und dateadd (Millisekunde, -1, bs.EndDateTime))) –

+0

@Billa, habe ich gerade meine ursprüngliche Post aktualisiert. Bitte werfen Sie einen Blick –

2

ok diese versuchen,

eine weitere CTE schaffen,

,cte2 as 
(
select * from @Holidays 
union all 
select BookingID,StartdateTime,EndDateTime from @EventBooking 
) 

dann wie gewohnt

AND not exists (select 1 
       from cte2 h 
       where cast(a.RepeatEventDate as date) between cast(h.startdatetime as date) and cast(h.enddatetime as date) 
       ) 

dies ist letzte (Datumzeit Konvertierung sehr verwirrend, ich von @Gordon Abfrage gerade erst begonnen.

AND not exists (select 1 
       from cte2 h 
       where cast(DATEADD(SECOND, DATEDIFF(SECOND, 0, StartTime), RepeatEventDate) as datetime) between cast(h.startdatetime as datetime) and cast(h.enddatetime as datetime) 
       ) 
+0

Ich möchte die Daten unter Ferien und EventBooking von meinem CTE entfernen, überprüfen Sie bitte meine sqlfiddle Link – Billa

+0

Sieht gut aus für Feiertage. Aber für EventBooking haben Sie alle Zeilen für den entsprechenden Tag entfernt. Bitte überprüfen Sie diese http://sqlfiddle.com/#!3/4e115/6 Ich muss nur die in EventBooking genannten Zeilen entfernen. – Billa

+0

@Billa Tut mir leid, dass ich Sie nicht bekommen habe. Welche Zeile ist falsch oder welche Zeile ist ausgelassen.Compare nur Datum oder Datetime beide? – KumarHarsh

1

Dies wird sicherlich helfen .....

WITH CTE AS (
      SELECT 
       S.ID, 
       S.StaffId , 
       S.StartdateTime, 
       S.EndDateTime, 
       H.StartdateTime 'HolydayStartDate' , 
       H.EndDateTime AS 'HolydayDateDate', 
       B.StartdateTime AS 'BookedStartDate', 
       B.EndDateTime AS 'BookedEndDate' 
      FROM @StaffSchedule S 
       LEFT JOIN @Holidays H ON S.StartdateTime >= H.StartdateTime AND S.EndDateTime <= H.EndDateTime 
       LEFT JOIN @BookedSchedules B ON B.StaffId = S.StaffId AND B.StartdateTime = S.StartdateTime AND B.EndDateTime = S.EndDateTime 
     ) 
     SELECT * FROM CTE 
     WHERE 
       HolydayStartDate IS NULL AND 
       HolydayDateDate IS NULL AND 
       BookedStartDate IS NULL AND 
       BookedEndDate IS NULL 
+0

@billa fragen Sie mich, gibt es irgendwelche Probleme in meiner Abfrage. – sureshhh

+0

Kannst du den Fiddle-Link bearbeiten und selbst überprüfen, ob dein Code funktioniert oder nicht? – Billa

+0

Überprüfen Sie diese http://sqlfiddle.com/#!3/07698/89 – sureshhh

2

RESULT = CTE - BookedSchedule - Urlaub

Wird gleich Satz Theorien verwenden Subtrahierenoperation, in SQL-Server können Sie Except (Minus in Oracle) verwenden.

select StaffId, StartdateTime,EndDateTime from StaffSchedule -- CTE 
    except 
    (select StaffId, StartdateTime,EndDateTime from BookedSchedules) -- BookedSchedule 
    except 
    (select StaffSchedule.StaffId, StaffSchedule.StartdateTime , StaffSchedule.EndDateTime 
    from StaffSchedule 
    inner join Holidays 
    on 
    cast(Holidays.StartdateTime As Date) = cast(StaffSchedule.StartdateTime As Date) 
    and 
    cast(Holidays.EndDateTime As Date) = cast(StaffSchedule.EndDateTime As Date) 
    )                 -- Holidays 
    ; 

Sqlfiddle demo

Wenn ein mehrtägiges Urlaub könnte eingeführt werden, wie:

INSERT dbo.Holidays (StartdateTime, EndDateTime) 
VALUES 
    ('2014-03-05 00:00:00.000', '2014-03-07 23:59:00.000'); 

die Abfrage Mit Gebrüll Personal-Urlaub extrahieren wird nützlich sein:

(select StaffSchedule.StaffId, StaffSchedule.StartdateTime , StaffSchedule.EndDateTime 
from StaffSchedule 
inner join Holidays 
on 
cast(Holidays.StartdateTime As Date) <= cast(StaffSchedule.StartdateTime As Date) 
and 
cast(Holidays.EndDateTime As Date) >= cast(StaffSchedule.EndDateTime As Date) 
) 
1

Um nach überlappenden Zeiträumen zu suchen, müssen Sie Folgendes tun:

Je nach Ihren Anforderungen kann es> =/< = anstelle von>/< sein.

Basierend auf Ihrer Geige:

with NonBookingSlots as 
(
select StartdateTime,EndDateTime from Holidays 
union all 
select StartdateTime,EndDateTime from BookedSchedules 
) 

SELECT 
    * 
FROM StaffSchedule as ss 
WHERE StaffId=1 

AND not exists (select * 
       from NonBookingSlots h 
       where h.StartdateTime < ss.enddatetime 
        and h.enddatetime > ss.startdatetime 
       ) 
2

Bitte versuchen:

select * From StaffSchedule 
where ID not in(
     select 
      ID 
     From StaffSchedule a inner join 
     (
      select StartdateTime, EndDateTime From dbo.BookedSchedules 
      union all 
      select StartdateTime, EndDateTime From dbo.Holidays 
     )b on a.StartdateTime between b.StartdateTime and b.EndDateTime and 
      a.EndDateTime between b.StartdateTime and b.EndDateTime) 

Chekck SQL Fiddle Demo

1

Ich denke, das wird für Sie arbeiten -

SELECT ss.* FROM StaffSchedule ss 
LEFT JOIN BookedSchedules bs 
    ON (ss.StartdateTime BETWEEN bs.StartdateTime AND bs.EndDateTime) 
    AND (ss.EndDateTime BETWEEN bs.StartdateTime AND bs.EndDateTime) 
LEFT JOIN Holidays h 
    ON (ss.StartdateTime BETWEEN h.StartdateTime AND h.EndDateTime) 
    AND (ss.EndDateTime BETWEEN h.StartdateTime AND h.EndDateTime) 
WHERE bs.ID IS NULL AND h.StartdateTime IS NULL AND h.EndDateTime IS NULL 

SQL Fiddle