2015-12-11 9 views
9

के बीच के महीनों में अवधि की गणना करें मेरे पास SQL ​​सर्वर में एक सारणी है जिसमें विभिन्न नौकरियों के लिए काम करने वाले उपयोगकर्ता की अवधि शामिल है। मुझे उपयोगकर्ता के लिए अनुभव की कुल संख्या की गणना करने की आवश्यकता है।टी-एसक्यूएल

Declare @temp table(Id int, FromDate DATETIME, ToDate DATETIME) 
INSERT INTO @temp (Id ,FromDate ,ToDate) 
VALUES (1 , '2003-1-08 06:55:56' , '2005-5-08 06:55:56'), 
     (2 , '2000-10-08 06:55:56' , '2008-7-08 06:55:56'), 
     (3 , '2013-6-08 06:55:56' , '2015-1-08 06:55:56'), 
     (4 , '2006-4-08 06:55:56' , '2011-3-08 06:55:56') 
SELECT * FROM @temp 

मैं अनुभव की कुल संख्या की गणना करना चाहता हूं;

Id FromDate ToDate  Difference IN Months 
=================================================== 
1 2003-01-08 2005-05-08 28 
2 2000-10-08 2008-07-08 93 
3 2013-06-08 2015-01-08 19 
4 2006-04-08 2011-03-08 59 

2000-2008 में 2003-2005 की तरह ओवरलैपिंग के वर्षों को हटाने के बाद; मैं कुछ इस तरह है:

Id FromDate ToDate  Difference IN Months 
===================================================  
1 2000-10-08 2011-03-08 125 
2 2013-06-08 2015-01-08 19 

तो जवाब 125+19 = 144 महीने होगा। कृपया मुझे समाधान खोजने में मदद करें।

+0

दिन का हिस्सा हमेशा 8 होता है? और इसलिए आपके पास कभी भी कोई आंशिक महीनों नहीं हैं जिन पर विचार करने की आवश्यकता है? –

+1

क्या आपने DATEDIFF फ़ंक्शन का प्रयास किया है? https://msdn.microsoft.com/en-us/library/ms189794.aspx – Vinnie

+0

SQL सर्वर का संस्करण क्या है? –

उत्तर

7

यहां सिंटैक्स सभी FromDate को ढूंढ रहा है जिसमें ओवरडैपिंग सेमडेट और टोडेट अंतराल नहीं है और सभी ToDates जिनमें ओवरडैपिंग सेडेटडेट और टोडेट अंतराल नहीं है। उन्हें एक rownumber देते दिनांक मान के अनुसार और उस rownumber पर उन्हें मिलान:

;WITH CTE as 
(
    SELECT min(Id) Id ,FromDate, row_number() over (ORDER BY FromDate) rn 
    FROM @temp x 
    WHERE 
    not exists 
     (SELECT * FROM @temp WHERE x.FromDate > FromDate and x.FromDate <= Todate) 
    GROUP BY FromDate 
), CTE2 as 
(
    SELECT Max(Id) Id ,ToDate, row_number() over (ORDER BY ToDate) rn 
    FROM @temp x 
    WHERE 
    not exists 
     (SELECT * FROM @temp WHERE x.ToDate >= FromDate and x.ToDate < Todate) 
    GROUP BY ToDate 
) 
SELECT SUM(DateDiff(month, CTE.FromDate, CTE2.ToDate)) 
FROM CTE 
JOIN CTE2 
ON CTE.rn = CTE2.rn 

परिणाम:

144 
+0

बिल्कुल वही जो मैं खोज रहा था, धन्यवाद –

+0

दरअसल, यह @ t-clausen.dk के सिर से एक अच्छा विचार है! –

3

आप इस

SELECT Set1.FromDate,MIN(List1.ToDate) AS ToDate, DATEDIFF(MONTH,Set1.FromDate,MIN(List1.ToDate)) 
    FROM @temp Set1 
    INNER JOIN @temp List1 ON Set1.FromDate <= List1.ToDate 
    AND NOT EXISTS(SELECT * FROM @temp List2 

    WHERE List1.ToDate >= List2.FromDate AND List1.ToDate < List2.ToDate) 
    WHERE NOT EXISTS(SELECT * FROM @temp Set2 
    WHERE Set1.FromDate > Set2.FromDate AND Set1.FromDate <= Set2.ToDate) 

    GROUP BY Set1.FromDate 
    ORDER BY Set1.FromDate 
1

कोशिश कर सकते हैं आप इस कोड की कोशिश कर सकते हैं:

DECLARE @temp TABLE (ID INT, FromDate DATETIME, ToDate DATETIME) 
INSERT INTO @temp (ID, FromDate, ToDate) 
VALUES (1 , '2003-1-08 06:55:56' , '2005-5-08 06:55:56'), 
     (2 , '2000-10-08 06:55:56' , '2008-7-08 06:55:56'), 
     (3 , '2013-6-08 06:55:56' , '2015-1-08 06:55:56'), 
     (4 , '2006-4-08 06:55:56' , '2011-3-08 06:55:56') 
SELECT 
    ID, 
    CONVERT(DATE, FromDate) AS FromDate, 
    CONVERT(DATE, ToDate) AS ToDate, 
    DATEDIFF(MONTH, FromDate, ToDate) AS [Difference IN Months] 
INTO #tmp 
FROM @temp 

SELECT T1.ID AS ID1, T2.ID AS ID2, T2.ToDate, T1.[Difference IN Months] + T2.[Difference IN Months] AS [Difference IN Months] 
INTO #tmp2 
FROM #tmp T1 
INNER JOIN #tmp T2 
    ON CAST(T1.ToDate AS DATE) = CAST(T2.FromDate AS DATE) 
     OR (YEAR(T1.ToDate) = YEAR(T2.FromDate) AND CAST(T1.ToDate AS DATE) < CAST(T2.FromDate AS DATE)) 
     OR YEAR(T1.ToDate) = YEAR(T2.FromDate) - 1 
DELETE #tmp WHERE ID IN (SELECT ID2 FROM #tmp2) 
UPDATE #tmp 
SET ToDate = (SELECT ToDate FROM #tmp2 WHERE #tmp.ID = ID1), 
    [Difference IN Months] = (SELECT [Difference IN Months] FROM #tmp2 WHERE #tmp.ID = ID1) 
WHERE ID IN (SELECT ID1 FROM #tmp2) 

SELECT 
    *, 
    ROW_NUMBER() OVER(ORDER BY FromDate) AS RF 
INTO #tmp3 
FROM #tmp 

SELECT T1.ID AS ID1, T2.ID AS ID2, T1.ToDate 
INTO #tmp4 
FROM #tmp3 T1 
    INNER JOIN #tmp3 T2 ON T1.RF = T2.RF + 1 
WHERE CAST(T1.FromDate AS DATE) < CAST(T2.ToDate AS DATE) 

UPDATE #tmp 
SET ToDate = (SELECT ToDate FROM #tmp4 WHERE #tmp.ID = ID2) 
WHERE ID IN (SELECT ID2 FROM #tmp4) 
DELETE #tmp WHERE ID IN (SELECT ID1 FROM #tmp4) 

UPDATE #tmp 
SET[Difference IN Months] = DATEDIFF(MONTH, FromDate, ToDate) 

SELECT 
    ROW_NUMBER() OVER(ORDER BY FromDate) AS ID, 
    FromDate, ToDate, [Difference IN Months] 
FROM #tmp 

DROP TABLE #tmp 
DROP TABLE #tmp2 
DROP TABLE #tmp3 
DROP TABLE #tmp4 

परिणाम:

ID FromDate ToDate  Difference IN Months 
===================================================  
1 2000-10-08 2011-03-08 125 
2 2013-06-08 2015-01-08 19 
संबंधित मुद्दे