Dati di esempio
DECLARE @StartDate date = '2016-06-01';
DECLARE @EndDate date = '2016-07-01';
DECLARE @Table_One TABLE (
Staff_ID int,
dt date,
First_Name nvarchar(50),
Last_Name nvarchar(50),
Section nvarchar(50),
Time_Worked datetime);
INSERT INTO @Table_One(Staff_ID, dt, First_Name, Last_Name, Section, Time_Worked)
VALUES
(1001, '2016-06-01', 'Bill', 'Price ', 'Level 1', '2016-06-01 8:30:00.000'),
(1001, '2016-06-05', 'Bill', 'Price ', 'Level 1', '2016-06-05 8:30:00.000'),
(1001, '2016-06-09', 'Bill', 'Price ', 'Level 1', '2016-06-09 8:30:00.000'),
(1001, '2016-06-12', 'Bill', 'Price ', 'Level 1', '2016-06-12 8:30:00.000'),
(1002, '2016-06-01', 'Mary', 'Somers', 'Level 1', '2016-06-01 8:30:00.000'),
(1002, '2016-06-05', 'Mary', 'Somers', 'Level 1', '2016-06-05 8:30:00.000'),
(1002, '2016-06-08', 'Mary', 'Somers', 'Level 1', '2016-06-08 8:30:00.000'),
(1003, '2016-06-03', 'Mark', 'Jones ', 'Level 1', '2016-06-03 8:30:00.000'),
(1003, '2016-06-05', 'Mark', 'Jones ', 'Level 1', '2016-06-05 8:30:00.000');
Interroga
La query utilizza CROSS APPLY
per "inserire" righe quando c'è uno spazio vuoto nelle date. Duplica la riga corrente tutte le volte necessarie utilizzando il tuo Tally
tabella dei numeri.
C'è una gestione speciale del caso quando il @StartDate
è precedente alla data della prima riga. Ecco perché ci sono due SELECTs
uniti insieme.
Il CTE.PrevDate IS NULL
filtra solo tali righe e vengono ripetute tutte le volte necessarie.
WITH
CTE
AS
(
SELECT *
,LAG(dt) OVER (PARTITION BY Staff_ID ORDER BY dt) AS PrevDate
,LEAD(dt) OVER (PARTITION BY Staff_ID ORDER BY dt) AS NextDate
FROM @Table_One AS T
)
SELECT
Staff_ID
,NewDate
,First_Name
,Last_Name
,Section
,CASE WHEN NewDate = dt THEN Time_Worked ELSE NULL END AS Time_Worked
FROM
CTE
CROSS APPLY
(
SELECT DATEADD(day, Tally.ID - 1, CTE.dt) AS NewDate
FROM dbo.Tally
WHERE Tally.ID <= DATEDIFF(day, CTE.dt, ISNULL(CTE.NextDate, @EndDate))
) AS CA_Next
UNION ALL
SELECT
Staff_ID
,NewDate
,First_Name
,Last_Name
,Section
,CASE WHEN NewDate = dt THEN Time_Worked ELSE NULL END AS Time_Worked
FROM
CTE
CROSS APPLY
(
SELECT DATEADD(day, - Tally.ID, CTE.dt) AS NewDate
FROM dbo.Tally
WHERE Tally.ID <= DATEDIFF(day, @StartDate, CTE.dt)
) AS CA_Prev
WHERE
CTE.PrevDate IS NULL
ORDER BY Staff_ID, NewDate;
Risultato
+----------+------------+------------+-----------+---------+-------------------------+
| Staff_ID | NewDate | First_Name | Last_Name | Section | Time_Worked |
+----------+------------+------------+-----------+---------+-------------------------+
| 1001 | 2016-06-01 | Bill | Price | Level 1 | 2016-06-01 08:30:00.000 |
| 1001 | 2016-06-02 | Bill | Price | Level 1 | NULL |
| 1001 | 2016-06-03 | Bill | Price | Level 1 | NULL |
| 1001 | 2016-06-04 | Bill | Price | Level 1 | NULL |
| 1001 | 2016-06-05 | Bill | Price | Level 1 | 2016-06-05 08:30:00.000 |
| 1001 | 2016-06-06 | Bill | Price | Level 1 | NULL |
| 1001 | 2016-06-07 | Bill | Price | Level 1 | NULL |
| 1001 | 2016-06-08 | Bill | Price | Level 1 | NULL |
| 1001 | 2016-06-09 | Bill | Price | Level 1 | 2016-06-09 08:30:00.000 |
| 1001 | 2016-06-10 | Bill | Price | Level 1 | NULL |
| 1001 | 2016-06-11 | Bill | Price | Level 1 | NULL |
| 1001 | 2016-06-12 | Bill | Price | Level 1 | 2016-06-12 08:30:00.000 |
| 1001 | 2016-06-13 | Bill | Price | Level 1 | NULL |
| 1001 | 2016-06-14 | Bill | Price | Level 1 | NULL |
| 1001 | 2016-06-15 | Bill | Price | Level 1 | NULL |
| 1001 | 2016-06-16 | Bill | Price | Level 1 | NULL |
| 1001 | 2016-06-17 | Bill | Price | Level 1 | NULL |
| 1001 | 2016-06-18 | Bill | Price | Level 1 | NULL |
| 1001 | 2016-06-19 | Bill | Price | Level 1 | NULL |
| 1001 | 2016-06-20 | Bill | Price | Level 1 | NULL |
| 1001 | 2016-06-21 | Bill | Price | Level 1 | NULL |
| 1001 | 2016-06-22 | Bill | Price | Level 1 | NULL |
| 1001 | 2016-06-23 | Bill | Price | Level 1 | NULL |
| 1001 | 2016-06-24 | Bill | Price | Level 1 | NULL |
| 1001 | 2016-06-25 | Bill | Price | Level 1 | NULL |
| 1001 | 2016-06-26 | Bill | Price | Level 1 | NULL |
| 1001 | 2016-06-27 | Bill | Price | Level 1 | NULL |
| 1001 | 2016-06-28 | Bill | Price | Level 1 | NULL |
| 1001 | 2016-06-29 | Bill | Price | Level 1 | NULL |
| 1001 | 2016-06-30 | Bill | Price | Level 1 | NULL |
| 1002 | 2016-06-01 | Mary | Somers | Level 1 | 2016-06-01 08:30:00.000 |
| 1002 | 2016-06-02 | Mary | Somers | Level 1 | NULL |
| 1002 | 2016-06-03 | Mary | Somers | Level 1 | NULL |
| 1002 | 2016-06-04 | Mary | Somers | Level 1 | NULL |
| 1002 | 2016-06-05 | Mary | Somers | Level 1 | 2016-06-05 08:30:00.000 |
| 1002 | 2016-06-06 | Mary | Somers | Level 1 | NULL |
| 1002 | 2016-06-07 | Mary | Somers | Level 1 | NULL |
| 1002 | 2016-06-08 | Mary | Somers | Level 1 | 2016-06-08 08:30:00.000 |
| 1002 | 2016-06-09 | Mary | Somers | Level 1 | NULL |
| 1002 | 2016-06-10 | Mary | Somers | Level 1 | NULL |
| 1002 | 2016-06-11 | Mary | Somers | Level 1 | NULL |
| 1002 | 2016-06-12 | Mary | Somers | Level 1 | NULL |
| 1002 | 2016-06-13 | Mary | Somers | Level 1 | NULL |
| 1002 | 2016-06-14 | Mary | Somers | Level 1 | NULL |
| 1002 | 2016-06-15 | Mary | Somers | Level 1 | NULL |
| 1002 | 2016-06-16 | Mary | Somers | Level 1 | NULL |
| 1002 | 2016-06-17 | Mary | Somers | Level 1 | NULL |
| 1002 | 2016-06-18 | Mary | Somers | Level 1 | NULL |
| 1002 | 2016-06-19 | Mary | Somers | Level 1 | NULL |
| 1002 | 2016-06-20 | Mary | Somers | Level 1 | NULL |
| 1002 | 2016-06-21 | Mary | Somers | Level 1 | NULL |
| 1002 | 2016-06-22 | Mary | Somers | Level 1 | NULL |
| 1002 | 2016-06-23 | Mary | Somers | Level 1 | NULL |
| 1002 | 2016-06-24 | Mary | Somers | Level 1 | NULL |
| 1002 | 2016-06-25 | Mary | Somers | Level 1 | NULL |
| 1002 | 2016-06-26 | Mary | Somers | Level 1 | NULL |
| 1002 | 2016-06-27 | Mary | Somers | Level 1 | NULL |
| 1002 | 2016-06-28 | Mary | Somers | Level 1 | NULL |
| 1002 | 2016-06-29 | Mary | Somers | Level 1 | NULL |
| 1002 | 2016-06-30 | Mary | Somers | Level 1 | NULL |
| 1003 | 2016-06-01 | Mark | Jones | Level 1 | NULL |
| 1003 | 2016-06-02 | Mark | Jones | Level 1 | NULL |
| 1003 | 2016-06-03 | Mark | Jones | Level 1 | 2016-06-03 08:30:00.000 |
| 1003 | 2016-06-04 | Mark | Jones | Level 1 | NULL |
| 1003 | 2016-06-05 | Mark | Jones | Level 1 | 2016-06-05 08:30:00.000 |
| 1003 | 2016-06-06 | Mark | Jones | Level 1 | NULL |
| 1003 | 2016-06-07 | Mark | Jones | Level 1 | NULL |
| 1003 | 2016-06-08 | Mark | Jones | Level 1 | NULL |
| 1003 | 2016-06-09 | Mark | Jones | Level 1 | NULL |
| 1003 | 2016-06-10 | Mark | Jones | Level 1 | NULL |
| 1003 | 2016-06-11 | Mark | Jones | Level 1 | NULL |
| 1003 | 2016-06-12 | Mark | Jones | Level 1 | NULL |
| 1003 | 2016-06-13 | Mark | Jones | Level 1 | NULL |
| 1003 | 2016-06-14 | Mark | Jones | Level 1 | NULL |
| 1003 | 2016-06-15 | Mark | Jones | Level 1 | NULL |
| 1003 | 2016-06-16 | Mark | Jones | Level 1 | NULL |
| 1003 | 2016-06-17 | Mark | Jones | Level 1 | NULL |
| 1003 | 2016-06-18 | Mark | Jones | Level 1 | NULL |
| 1003 | 2016-06-19 | Mark | Jones | Level 1 | NULL |
| 1003 | 2016-06-20 | Mark | Jones | Level 1 | NULL |
| 1003 | 2016-06-21 | Mark | Jones | Level 1 | NULL |
| 1003 | 2016-06-22 | Mark | Jones | Level 1 | NULL |
| 1003 | 2016-06-23 | Mark | Jones | Level 1 | NULL |
| 1003 | 2016-06-24 | Mark | Jones | Level 1 | NULL |
| 1003 | 2016-06-25 | Mark | Jones | Level 1 | NULL |
| 1003 | 2016-06-26 | Mark | Jones | Level 1 | NULL |
| 1003 | 2016-06-27 | Mark | Jones | Level 1 | NULL |
| 1003 | 2016-06-28 | Mark | Jones | Level 1 | NULL |
| 1003 | 2016-06-29 | Mark | Jones | Level 1 | NULL |
| 1003 | 2016-06-30 | Mark | Jones | Level 1 | NULL |
+----------+------------+------------+-----------+---------+-------------------------+
Inserimento delle righe generate nella tabella originale
All'inizio non mi ero reso conto che vuoi cambiare la tabella originale, quindi ho scritto un SELECTs
query che restituisce un set di risultati necessario. È facile regolarlo su INSERT
query che aggiungerebbe nuove righe nella tabella originale.
Tutto quello che ho fatto è stato aggiungere un filtro WHERE NewDate <> dt
, che garantisce che vengano inserite solo le nuove righe che prima non esistevano.
WITH
CTE
AS
(
SELECT
Staff_ID
,dt
,First_Name
,Last_Name
,Section
,Time_Worked
,LAG(dt) OVER (PARTITION BY Staff_ID ORDER BY dt) AS PrevDate
,LEAD(dt) OVER (PARTITION BY Staff_ID ORDER BY dt) AS NextDate
FROM @Table_One AS T
)
INSERT INTO @Table_One(Staff_ID, dt, First_Name, Last_Name, Section, Time_Worked)
SELECT
Staff_ID
,NewDate
,First_Name
,Last_Name
,Section
,NULL AS Time_Worked
FROM
CTE
CROSS APPLY
(
SELECT DATEADD(day, Tally.ID - 1, CTE.dt) AS NewDate
FROM dbo.Tally
WHERE Tally.ID <= DATEDIFF(day, CTE.dt, ISNULL(CTE.NextDate, @EndDate))
) AS CA_Next
WHERE
NewDate <> dt
UNION ALL
SELECT
Staff_ID
,NewDate
,First_Name
,Last_Name
,Section
,NULL AS Time_Worked
FROM
CTE
CROSS APPLY
(
SELECT DATEADD(day, - Tally.ID, CTE.dt) AS NewDate
FROM dbo.Tally
WHERE Tally.ID <= DATEDIFF(day, @StartDate, CTE.dt)
) AS CA_Prev
WHERE
CTE.PrevDate IS NULL
ORDER BY Staff_ID, NewDate;
Risultato
Per verificare il risultato basta SELECTs
tutto dalla tabella originale.
SELECT * FROM @Table_One ORDER BY Staff_ID, dt;
Il risultato è lo stesso mostrato sopra.