忽略CTE的日期列表

时间:2014-02-21 13:04:41

标签: sql sql-server sql-server-2008

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

我想从我的CTE中删除holidays and EventBooking下的日期。 我的意思是从我的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

7 个答案:

答案 0 :(得分: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))

答案 1 :(得分:2)

好的尝试一下,

  

再创建一个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)
               )

答案 2 :(得分:2)

  

结果= CTE - BookedSchedule - 假期

将等于使用set theory subtract operation,在sql server中你可以使用Except(Oracle中的减号)。

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

答案 3 :(得分: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

答案 4 :(得分: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 

答案 5 :(得分:1)

要检查您需要执行的重叠时段:

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

根据您的需要,可能是&gt; = /&lt; =而不是&gt; /&lt;。

基于你的小提琴:

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
               )

答案 6 :(得分: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