Sqlserver
 sql >> डेटाबेस >  >> RDS >> Sqlserver

दो तिथियों के बीच लापता तिथियों को सम्मिलित करने के लिए टैली तालिका? एसक्यूएल

नमूना डेटा

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');

क्वेरी

क्वेरी CROSS APPLY का उपयोग करती है तिथियों में अंतर होने पर पंक्तियों को "सम्मिलित" करने के लिए। यह आपके Tally . का उपयोग करके वर्तमान पंक्ति को जितनी बार आवश्यक हो डुप्लिकेट करता है संख्याओं की तालिका।

@StartDate . होने पर मामले को विशेष रूप से हैंडल किया जाता है पहली पंक्ति की तारीख से पहले है। इसलिए दो SELECTs हैं एक साथ मिल गए।

CTE.PrevDate IS NULL केवल ऐसी पंक्तियों को फ़िल्टर करता है और उन्हें आवश्यकतानुसार कई बार दोहराया जाता है।

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;

परिणाम

+----------+------------+------------+-----------+---------+-------------------------+
| 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                    |
+----------+------------+------------+-----------+---------+-------------------------+

जेनरेट की गई पंक्तियों को वापस मूल तालिका में सम्मिलित करना

पहले तो मुझे एहसास नहीं हुआ कि आप मूल तालिका को बदलना चाहते हैं, इसलिए मैंने एक SELECT wrote लिखा क्वेरी जो एक आवश्यक परिणाम सेट लौटाती है। इसे INSERT . में समायोजित करना आसान है क्वेरी जो मूल तालिका में नई पंक्तियाँ जोड़ेगी।

मैंने केवल एक फिल्टर जोड़ा है WHERE NewDate <> dt , जो सुनिश्चित करता है कि केवल नई पंक्तियाँ डाली जाएँ जो पहले मौजूद नहीं थीं।

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;

परिणाम

रिजल्ट चेक करने के लिए बस SELECT मूल तालिका से सब कुछ।

SELECT * FROM @Table_One ORDER BY Staff_ID, dt;

परिणाम वही है जो ऊपर दिखाया गया है।



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. पंक्ति दर पंक्ति के बजाय एक बार में संपूर्ण डेटाटेबल को डेटाबेस में सम्मिलित करें?

  2. SQL सर्वर में DELETE पास-थ्रू क्वेरी कैसे करें

  3. SQL सर्वर में डेटा प्रकार की आईडी प्राप्त करने के लिए TYPE_ID() का उपयोग करें

  4. SQL सर्वर में "पंक्ति संस्करण" क्या है?

  5. SQL सर्वर में नामकरण मानकों या नामकरण सम्मेलन के अनुसार सभी डिफ़ॉल्ट बाधाओं का नाम कैसे बदलें - SQL सर्वर / TSQL ट्यूटोरियल भाग 93