2014-02-21 46 views
5

CTE給出了以下結果忽略來自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 

我也有假期

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

而且EventBooking

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

我想刪除的日期屬於holidays and EventBooking從我的CTE。 我的意思是從我的CTE刪除(X) recods

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) 
       ) 

這裏是我的SQL FIDDLE DEMO

+0

由於您的設計中沒有日曆實體,因此使用表掃描查詢以獲得所需結果是不可避免的。 BTW當前表需要加入日期字段,這意味着無效但高效的解決方案。 –

+0

你試過我的查詢嗎?它返回你想要的。 – dnoeth

回答

4

好的假設這是你的架構

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'); 

這是否解決了您的問題?

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

缺少'Id = 2'記錄。只顯示一條記錄。 CHeck this http://sqlfiddle.com/#!3/07698/46 – Billa

+0

爲了避免關係,你不能只加一毫秒的邊距值? SELECT * FROM StaffSchedule SS 其中 不存在(選擇1從NonBookingSlots BS 其中(ss.StartdateTime \t \t \t \t \t \t DATEADD(微差,1,bs.StartdateTime)和DATEADD(毫秒,-1之間, bs.EndDateTime))) –

+0

@Billa,我剛剛更新了我的第一篇文章。請看看 –

2

OK試試這個,

創造一個更CTE,

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

然後像往常一樣

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) 
       ) 

這是一個最新的(日期時間轉換非常混亂,我剛從@Gordon查詢開始 。

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

我想刪除假日期間的日期和從我的CTE的EventBooking,請檢查我的sqlfiddle鏈接 – Billa

+0

看起來不錯假期。但是對於EventBooking,您刪除了相應日期的所有行。請檢查http://sqlfiddle.com/#!3/4e115/6我只需要刪除EventBooking中提到的行。 – Billa

+0

@Billa對不起,我沒有得到you.which行是錯誤的或哪一行是deleted.compare只有日期或日期時間都? – KumarHarsh

1

這一定會幫助你.....

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問我在我的查詢中是否有任何問題。 – sureshhh

+0

你可以編輯我給出的小提琴鏈接,並自己檢查你的代碼是否正常工作? – Billa

+0

檢查http://sqlfiddle.com/#!3/07698/89 – sureshhh

2

RESULT = CTE - BookedSchedule - 假日

將等於用一套理論減法操作中,您可以使用的SQL服務器Except(Oracle中的Minus)。

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

如果多天的假期可以插入,如:

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

使用查詢波紋管,提取職工假期將是有益的:

(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

要檢查重疊期間,您需要做:

where p1.StartdateTime < p2.enddatetime 
    and p1.enddatetime > p2.startdatetime 

根據您的需要,它可能> =/< =而不是>/<。

根據您的提琴:

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

請嘗試:

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

我認爲這會爲你工作 -

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