Since I already had it written out...
/* ===================================================================
Start by creating some test data....
=================================================================== */
IF OBJECT_ID('tempdb..#LogTimeInfo', 'U') IS NULL
BEGIN -- DROP TABLE #LogTimeInfo;
CREATE TABLE #LogTimeInfo (
EmployeeID INT NOT NULL,
LoginDT DATETIME NOT NULL,
LogoutDT DATETIME NOT NULL,
PRIMARY KEY CLUSTERED (LoginDT, EmployeeID)
WITH (IGNORE_DUP_KEY = ON)
);
WITH
cte_n1 (n) AS (SELECT 1 FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n (n)),
cte_n2 (n) AS (SELECT 1 FROM cte_n1 a CROSS JOIN cte_n1 b),
cte_n3 (n) AS (SELECT 1 FROM cte_n2 a CROSS JOIN cte_n2 b),
cte_Tally (n) AS (
SELECT TOP (1000000)
ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM
cte_n3 a CROSS JOIN cte_n3 b
)
INSERT #LogTimeInfo (EmployeeID, LoginDT, LogoutDT)
SELECT
ROW_NUMBER() OVER (PARTITION BY rd.rand_day ORDER BY t.n),
rit.rand_in_time,
rot.rand_out_time
FROM
cte_Tally t
CROSS APPLY ( VALUES (DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)) ) td (today)
CROSS APPLY ( VALUES (DATEADD(DAY, -1 * ABS(CHECKSUM(NEWID())) % 500, td.today)) ) rd (rand_day) -- 500 day range
CROSS APPLY ( VALUES (DATEADD(MINUTE, ABS(CHECKSUM(NEWID())) % 301 + 300, rd.rand_day)) ) rit (rand_in_time) -- between 5:00 am & 10: am
CROSS APPLY ( VALUES (DATEADD(MINUTE, ABS(CHECKSUM(NEWID())) % 301 + 300, rit.rand_in_time)) ) rot (rand_out_time); -- betweem 5 & 10 hours after clockin
END;
/* ===================================================================
The actual solution....
=================================================================== */
DECLARE @today DATETIME = CONVERT(DATE, GETDATE());
WITH -- Use the cte to create a virtual calendar table that has all dates within the desired date range.
cte_n1 (n) AS (SELECT 1 FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n (n)),
cte_n2 (n) AS (SELECT 1 FROM cte_n1 a CROSS JOIN cte_n1 b),
cte_Dates (d) AS (
SELECT TOP (365)
DATEADD(DAY, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 366, @today)
FROM
cte_n2 a CROSS JOIN cte_n2 b
)
SELECT
d.d,
[00:00] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 30 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 0, d.d) THEN 1 END),
[00:30] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 60 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 30, d.d) THEN 1 END),
[01:00] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 90 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 60, d.d) THEN 1 END),
[01:30] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 120 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 90, d.d) THEN 1 END),
[02:00] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 150 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 120, d.d) THEN 1 END),
[02:30] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 180 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 150, d.d) THEN 1 END),
[03:00] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 210 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 180, d.d) THEN 1 END),
[03:30] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 240 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 210, d.d) THEN 1 END),
[04:00] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 270 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 240, d.d) THEN 1 END),
[04:30] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 300 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 270, d.d) THEN 1 END),
[05:00] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 330 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 300, d.d) THEN 1 END),
[05:30] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 360 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 330, d.d) THEN 1 END),
[06:00] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 390 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 360, d.d) THEN 1 END),
[06:30] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 420 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 390, d.d) THEN 1 END),
[07:00] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 450 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 420, d.d) THEN 1 END),
[07:30] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 480 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 450, d.d) THEN 1 END),
[08:00] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 510 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 480, d.d) THEN 1 END),
[08:30] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 540 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 510, d.d) THEN 1 END),
[09:00] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 570 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 540, d.d) THEN 1 END),
[09:30] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 600 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 570, d.d) THEN 1 END),
[10:00] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 630 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 600, d.d) THEN 1 END),
[10:30] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 660 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 630, d.d) THEN 1 END),
[11:00] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 690 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 660, d.d) THEN 1 END),
[11:30] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 720 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 690, d.d) THEN 1 END),
[12:00] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 750 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 720, d.d) THEN 1 END),
[12:30] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 780 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 750, d.d) THEN 1 END),
[13:00] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 810 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 780, d.d) THEN 1 END),
[13:30] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 840 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 810, d.d) THEN 1 END),
[14:00] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 870 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 840, d.d) THEN 1 END),
[14:30] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 900 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 870, d.d) THEN 1 END),
[15:00] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 930 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 900, d.d) THEN 1 END),
[15:30] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 960 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 930, d.d) THEN 1 END),
[16:00] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 990 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 960, d.d) THEN 1 END),
[16:30] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 1020 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 990, d.d) THEN 1 END),
[17:00] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 1050 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 1020, d.d) THEN 1 END),
[17:30] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 1080 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 1050, d.d) THEN 1 END),
[18:00] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 1110 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 1080, d.d) THEN 1 END),
[18:30] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 1140 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 1110, d.d) THEN 1 END),
[19:00] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 1170 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 1140, d.d) THEN 1 END),
[19:30] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 1200 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 1170, d.d) THEN 1 END),
[20:00] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 1230 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 1200, d.d) THEN 1 END),
[20:30] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 1260 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 1230, d.d) THEN 1 END),
[21:00] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 1290 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 1260, d.d) THEN 1 END),
[21:30] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 1320 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 1290, d.d) THEN 1 END),
[22:00] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 1350 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 1320, d.d) THEN 1 END),
[22:30] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 1380 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 1350, d.d) THEN 1 END),
[23:00] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 1410 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 1380, d.d) THEN 1 END),
[23:30] = COUNT(CASE WHEN lti.LoginDT < DATEADD(MINUTE, 1440 , d.d) AND lti.LogoutDT > DATEADD(MINUTE, 1410, d.d) THEN 1 END)
FROM
cte_Dates d
LEFT JOIN #LogTimeInfo lti
ON d.d <= lti.LoginDT
AND DATEADD(DAY, 1, d.d) > lti.LoginDT
GROUP BY
d.d;