I have employee shift table, and then attendance table. I would like to know the shifts which the employee has not attended.
Below is the query to create sample tables.
DECLARE @InsideOutsideTable TABLE
(
FromTime DATETIME,
ToTime DATETIME
)
DECLARE @ShiftTable TABLE
(
FromDateTime DATETIME,
ToDateTime DATETIME
)
INSERT INTO @ShiftTable VALUES ('2018-05-02 07:30:00.000','2018-05-02 12:30:00.000')
INSERT INTO @ShiftTable VALUES ('2018-05-02 01:30:00.000','2018-05-02 16:30:00.000')
INSERT INTO @InsideOutsideTable VALUES ('2018-05-02 07:24:00.000','2018-05-02 11:47:00.000')
INSERT INTO @InsideOutsideTable VALUES ('2018-05-02 18:07:00.000','2018-05-02 18:32:00.000')
Below is my query to bring the shifts which employee not attended.
SELECT
S.*
FROM @ShiftTable S
CROSS APPLY @InsideOutsideTable T
WHERE S.FromDateTime NOT BETWEEN T.FromTime AND T.ToTime
AND S.ToDateTime NOT BETWEEN T.FromTime AND T.ToTime
But it is returning every row. Can you help me achieve my requirement?
Expected output:
FromDateTime ToDateTime
2018-05-02 01:30:00.000 2018-05-02 16:30:00.000
A big thanks in advance.
you may use this
DECLARE @InsideOutsideTable TABLE
(
FromTime DATETIME,
ToTime DATETIME
)
DECLARE @ShiftTable TABLE
(
ID Int,
FromDateTime DATETIME,
ToDateTime DATETIME
)
INSERT INTO @ShiftTable VALUES (1,'2018-05-02 07:30:00.000','2018-05-02 12:30:00.000')
INSERT INTO @ShiftTable VALUES (2,'2018-05-02 13:30:00.000','2018-05-02 16:30:00.000')
INSERT INTO @InsideOutsideTable VALUES ('2018-05-02 07:24:00.000','2018-05-02 11:47:00.000')
INSERT INTO @InsideOutsideTable VALUES ('2018-05-02 18:07:00.000','2018-05-02 18:32:00.000')
SELECT S.*
FROM @ShiftTable S
WHERE ID NOT IN (
SELECT
S.ID
FROM @ShiftTable S
INNER JOIN @InsideOutsideTable T
ON ( ( T.FromTime <= S.ToDateTime AND T.FromTime >= S.FromDateTime )
OR ( T.ToTime <= S.ToDateTime AND T.ToTime >= S.FromDateTime )
OR ( T.FromTime <= S.FromDateTime AND T.ToTime >= S.ToDateTime )
)
AND T.FromTime <= S.ToDateTime
)
take care that you defined 1:30 not 13:30
Use this query:
SELECT *
FROM
(SELECT
S.*,
(SELECT
count(*)
FROM @InsideOutsideTable T
WHERE T.FromTime BETWEEN S.FromDateTime AND S.ToDateTime
OR T.ToTime BETWEEN S.FromDateTime AND S.ToDateTime) AS cnt
FROM @ShiftTable S) AS tbl
WHERE cnt = 0
I think you are looking for full overlaps between between the two tables. If so,the simplest approach is a LEFT JOIN
or NOT EXISTS
:
SELECT S.*
FROM @ShiftTable S LEFT JOIN
@InsideOutsideTable T
ON S.FromDateTime <= T.FromTime AND
S.ToDateTime >= T.ToTime
WHERE T.ToTime IS NULL;
Here is a rextester .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.