CTE_Users geeft ons een lijst van alle gebruikers met start- en einddatums voor elke gebruiker.
Het is gekoppeld aan de Calendar tabel om rij te genereren voor elke datum voor elke gebruiker.
Ten slotte wordt het samengevoegd met de hoofdtabel Test om Total terug te geven voor elke datum. ISNULL zorgt ervoor dat de datums die geen gegevens hebben 0 retourneren.
WITH
CTE_Users
AS
(
SELECT
Userid
,MIN(startdate) AS StartDate
,MAX(enddate) AS EndDate
FROM TEST
GROUP BY Userid
)
SELECT
ROW_NUMBER() OVER (ORDER BY CTE_Users.Userid, Calendar.dt) AS ID
,CTE_Users.Userid
,T.Id1
,Calendar.dt
,ISNULL(T.Total, 0) AS Total
FROM
CTE_Users
INNER JOIN Calendar ON
Calendar.dt >= CTE_Users.StartDate
AND Calendar.dt <= CTE_Users.EndDate
LEFT JOIN TEST AS T ON
T.Userid = CTE_Users.Userid
AND T.date1 = Calendar.dt
ORDER BY CTE_Users.Userid, Calendar.dt;
Resultaat
| ID | Userid | Id1 | dt | Total |
|----|--------|--------|------------|-------|
| 1 | abc | 1 | 2015-01-13 | 200 |
| 2 | abc | 2 | 2015-01-14 | 200 |
| 3 | abc | 3 | 2015-01-15 | 200 |
| 4 | abc | (null) | 2015-01-16 | 0 |
| 5 | abc | (null) | 2015-01-17 | 0 |
| 6 | abc | (null) | 2015-01-18 | 0 |
| 7 | abc | 4 | 2015-01-19 | 200 |
| 8 | abc | 5 | 2015-01-20 | 200 |
| 9 | abc | (null) | 2015-01-21 | 0 |
| 10 | abc | (null) | 2015-01-22 | 0 |
| 11 | abc | 6 | 2015-01-23 | 200 |
| 12 | abc | 7 | 2015-01-24 | 200 |
| 13 | def | (null) | 2015-02-10 | 0 |
| 14 | def | (null) | 2015-02-11 | 0 |
| 15 | def | 8 | 2015-02-12 | 200 |
| 16 | def | 9 | 2015-02-13 | 200 |
| 17 | def | (null) | 2015-02-14 | 0 |
| 18 | def | 10 | 2015-02-15 | 200 |
| 19 | def | 11 | 2015-02-16 | 200 |
| 20 | def | 12 | 2015-02-17 | 200 |
| 21 | def | 13 | 2015-02-18 | 200 |
| 22 | def | (null) | 2015-02-19 | 0 |
| 23 | def | (null) | 2015-02-20 | 0 |
ID is een rijnummer dat direct wordt gegenereerd.Id1 zijn originele ID's van de Test tafel.
Ik zou Calendar . genereren tabel als volgt:
CREATE TABLE [Calendar](
[dt] [date] NOT NULL
CONSTRAINT [PK_Calendar] PRIMARY KEY CLUSTERED
(
[dt] ASC
));
-- 10K dates from 2000-01-01 till 2027-05-18
INSERT INTO Calendar (dt)
SELECT TOP (10000)
DATEADD(day, ROW_NUMBER() OVER (ORDER BY s1.[object_id])-1, '2000-01-01') AS dt
FROM sys.all_objects AS s1 CROSS JOIN sys.all_objects AS s2
OPTION (MAXDOP 1);