Konfiguracja, więc jesteśmy pewni, że mówimy o tym samym:
USE tempdb;
GO
CREATE TABLE dbo.users
(
[user_id] INT IDENTITY(1,1) PRIMARY KEY,
hired_date DATE NOT NULL,
termination_date DATE
);
CREATE TABLE dbo.[date table]
(
week_start DATE NOT NULL UNIQUE,
week_end AS CONVERT(DATE, DATEADD(DAY, 6, week_start))
);
GO
SET NOCOUNT ON;
GO
INSERT dbo.[date table](week_start) VALUES
('20110806'),
('20110813'),
('20110820');
INSERT dbo.users(hired_date, termination_date) VALUES
('20110101', NULL), -- long-time, active
('20110101', '20110807'), -- long-time, fired in week 1
('20110807', '20110815'), -- hired week 1, fired week 2
('20110816', '20110816'), -- hired week 2, fired week 2
('20110807', '20110825'), -- hired week 1, fired week 3
('20110806', NULL), -- hired week 1, active
('20110807', NULL), -- hired week 1, active
('20110813', NULL), -- hired week 2, active
('20110821', NULL); -- hired week 3, active
GO
Przy tej logice powinno być 6 aktywnych pracowników w tygodniu 1, 7 aktywnych pracowników w tygodniu 2 i z powrotem do 6 w tygodniu 3. Zajęło mi kilka minut i narysowanie aktywnych linii na kartce papieru, aby dowiedzieć się, gdzie Popełniłem błąd w moim zapytaniu. Teraz spróbujmy to porównać z przykładowymi danymi, które ustawiliśmy w tempdb:
;WITH last_8_weeks AS
(
SELECT TOP (8) week_start, week_end
FROM dbo.[date table]
WHERE week_start >= DATEADD(WEEK, -9, CURRENT_TIMESTAMP)
ORDER BY week_start DESC
)
SELECT d.week_end, COUNT(u.user_id)
FROM last_8_weeks AS d
LEFT OUTER JOIN dbo.users AS u
ON u.hired_date <= d.week_end
AND COALESCE(u.termination_date, DATEADD(DAY, 1, d.week_end)) >= d.week_start
GROUP BY d.week_end
ORDER BY d.week_end;
A potem posprzątaj:
GO
DROP TABLE dbo.[date table], dbo.users;