2013-10-14 3 views
5

मुझे हाल ही में नियोजन की तिथियों के बीच अंतर खोजने के लिए काम सौंपा गया था, जहां एक अंतर को एक नौकरी के अंत से 30 दिनों से अधिक समय की अवधि के रूप में परिभाषित किया गया है अगले, और कहा कि सूट करने के लिए एक प्रश्न के साथ आ पा रहा था की, नीचे देखें:एसक्यूएल सर्वर - ओवरलैपिंग तिथियों को शामिल करने वाली तिथियों के बीच अंतराल खोजें

WITH GapsInEmployment AS 
(
    SELECT 
    -1 AS DriverQualificationApplicationEmploymentGapId 
    ,E1.DriverQualificationApplicationId 
    ,E1.EndDate AS EmploymentGapBeginDate 
    ,E2.StartDate AS EmploymentGapEndDate 
    ,(
     CASE 
      WHEN ISNULL(DATEDIFF(DD, E1.EndDate, E2.StartDate), 0) < 0 THEN 0 
      ELSE DATEDIFF(DD, E1.EndDate, E2.StartDate) 
     END 
     ) AS DaysLapsedBetweenEmployment 
     ,NULL AS ReasonForEmploymentGap 
    FROM @EmploymentGapInfo E1 
    LEFT JOIN @EmploymentGapInfo E2 
     ON E1.RowNum = E2.RowNum - 1 
) 

SELECT * 
FROM GapsInEmployment 
WHERE DaysLapsedBetweenEmployment > 30; 

मैं, एक रिकॉर्ड की तुलना कर रहा हूँ अगले रिकॉर्ड करने के लिए, 30 के एक चूक हो, तो देखने के लिए पहले रिकॉर्ड की समाप्ति तिथि और दूसरे की आरंभ तिथि के बीच के दिनों, जो "सामान्य" मामलों के लिए ठीक काम करता है, यानी जहां रोजगार की अवधि ओवरलैप नहीं होती है। खैर कि विशेष मामला सामने आया है, जहां किसी विशेष समय अवधि के दौरान किसी एक से अधिक नौकरी होती है, और जॉब ए की समय अवधि उस कर्मचारी के बीच होती है जब कर्मचारी के पास जॉब बी था। ऊपर दिए गए प्रश्न के साथ परीक्षण डेटा यहां दिया गया है:

DECLARE @EmploymentGapInfo TABLE 
(
    RowNum INT IDENTITY(1, 1) 
    ,DriverQualificationApplicationEmploymentId INT 
    ,DriverQualificationApplicationId INT 
    ,StartDate DATETIME 
    ,EndDate DATETIME 
); 
INSERT INTO @EmploymentGapInfo 
SELECT -1, 766, '10/14/2003', '11/07/2003'; 

INSERT INTO @EmploymentGapInfo 
SELECT -1, 766, '08/28/2006', '06/15/2011'; 

INSERT INTO @EmploymentGapInfo 
SELECT -1, 766, '08/22/2011', '10/23/2012'; 

INSERT INTO @EmploymentGapInfo 
SELECT -1, 766, '06/01/2012', '07/01/2012'; 

INSERT INTO @EmploymentGapInfo 
SELECT -1, 766, '11/01/2012', '03/05/2013'; 

INSERT INTO @EmploymentGapInfo 
SELECT -1, 766, '10/14/2013', NULL; 

आप क्वेरी चलाते हैं, तो इसे गलत तरीके से 2012/07/01 और 2012/11/01 के बीच एक रोजगार की खाई है, जो कि रिकार्ड के लिए प्रारंभ दिनांक और समाप्ति तिथि के रूप में सही नहीं है की गणना के पिछले रिकॉर्ड के बीच शुरू होता है । क्वेरी अंतराल के लिए निम्नलिखित परिणाम सेट का उत्पादन करना चाहिए:

11/07/2003 -> 08/28/2006

06/15/2011 -> 08/22/2011

03/05/2013 -> 10/14/2013

मेरी समस्या यह है कि, मैं कर्सर के बिना इसे सही तरीके से गणना करने के लिए एक तरीके से आने की कोशिश कर रहा हूं, जिस तरह से मैं कोशिश कर रहा हूं, मुझे प्रत्येक के माध्यम से लूपिंग करना होगा EmploymentGapInfo तालिका चर में रिकॉर्ड करें, और एक बार मेरे पास उस रिकॉर्ड के लिए प्रारंभ और समाप्ति तिथियां हों, फिर तालिका के माध्यम से लूप को यह देखने के लिए कि प्रारंभ तिथि और समाप्ति तिथि तालिका में किसी अन्य रिकॉर्ड को ओवरलैप करती है या नहीं।

क्या कोई तरीका है कि मैं इस समस्या को कर्सर का उपयोग करने की बजाय सेट-आधारित दृष्टिकोण से निपट सकता हूं? क्या यह एक समस्या होगी जो डेटाबेस परत में इसे हल करने की कोशिश कर रहे व्यवसाय परत में किए जाने से लाभान्वित होगी?

किसी भी मदद की सराहना की जाएगी।

+1

कोशिश: // sqlfiddle।कॉम /) डेमो और यहां लिंक दें – th1rdey3

+0

अंतिम अंतर ('03/05/2013 -> 10/14/2013') गलत है क्योंकि यह पंक्ति' 10/14/2012 -> नल' है। –

+0

@ th1rdey3: यहां SQL Fiddle का लिंक है: http://sqlfiddle.com/#!3/06753/3/0 – rc6886

उत्तर

0

आप अपने @EmploymentGapInfo की सभी तिथियों के साथ एक अस्थायी तालिका बना सकते हैं जो आरोही क्रम में क्रमबद्ध है। इसके बाद अंतराल को ढूंढना अधिक आसान होता है।

select distinct StartDate 'GDate' 
from @EmploymentGapInfo 
union 
select distinct EndDate 
from @EmploymentGapInfo 
0

हो सकता है कि एक पुराने पोस्ट करने के लिए ... लेकिन यहाँ जवाब है::

सबसे पहले, आप posibility को निकाल देता

क्वेरी सभी तिथियों ऐसा दिखाई दे सकता प्राप्त करने के लिए ओवरलैपिंग श्रेणियां रखने के लिए, और एक गैर ओवरलैप रेंज सूची में परिणाम व्यक्त करें। यही कारण है कि एक आसान काम नहीं है, तो आप इस क्वेरी के साथ Cando:

SELECT * 
    INTO #TEMP 
    FROM 
    (
      SELECT DriverQualificationApplicationEmploymentId, DriverQualificationApplicationId, Min(NewStartDate) StartDate, MAX(EndDate) EndDate 
      FROM 
      (
       SELECT DriverQualificationApplicationEmploymentId, DriverQualificationApplicationId, StartDate, EndDate, 
         NewStartDate = Range_UNTIL_NULL.StartDate + NUMBERS.number, 
         NewStartDateGroup =  DATEADD(d, 
                1 - DENSE_RANK() OVER (PARTITION BY DriverQualificationApplicationEmploymentId, DriverQualificationApplicationId ORDER BY Range_UNTIL_NULL.StartDate + NUMBERS.number), 
                Range_UNTIL_NULL.StartDate + NUMBERS.number) 
       FROM 
       (
         SELECT 
          DriverQualificationApplicationEmploymentId, DriverQualificationApplicationId, StartDate, ISNULL(EndDate, dateadd(d,1,StartDate)) AS EndDate 
         FROM @EmploymentGapInfo T1 
         WHERE 
          NOT EXISTS ( SELECT * 
              FROM @EmploymentGapInfo t2 
              WHERE T1.DriverQualificationApplicationEmploymentId = t2.DriverQualificationApplicationEmploymentId AND 
                T1.DriverQualificationApplicationId = T2.DriverQualificationApplicationId and 
                T1.StartDate > T2.StartDate AND T2.EndDate IS NULL 
             ) 
       ) AS Range_UNTIL_NULL 
       CROSS APPLY Enumerate (ABS(DATEDIFF(d, StartDate, EndDate))) AS NUMBERS 
        ) X 
      GROUP BY DriverQualificationApplicationEmploymentId, DriverQualificationApplicationId, NewStartDateGroup 
    ) OVERLAPED_RANGES_WITH_COUNT 
    ORDER BY DriverQualificationApplicationEmploymentId, DriverQualificationApplicationId, StartDate  

और फिर आप 30 दिन से अधिक होने अंतराल की गणना कर सकते हैं:

SELECT 
    EndDate AS StartGap, 
    (SELECT MIN(StartDate) FROM #temp t3 WHERE t3.startdate > t1.endDate) AS EndGap 
FROM #TEMP t1 
WHERE EndDate + 30 < (SELECT Min(startDate) FROM #temp t2 WHERE t2.startdate > t1.endDate) 
4

एसक्यूएल सर्वर 2012 और इसके बाद के संस्करण के लिए महान समाधान। पर एक बाउचर को सभी क्रेडिट टॉम पूछना एक [SqlFiddle] (http बनाने https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:529176000346581356

select * 
from (
     select 
     max(enddate) over (order by startdate) start_range 
     ,lead(startdate) over (order by startdate) end_range 
     from @EmploymentGapInfo 
    ) as c 
where c.start_range < c.end_range 
+0

मुझे पता है कि यह वास्तव में पुराना है, लेकिन मैं सिर्फ धन्यवाद कहना चाहता था! इसने एक बहुत ही समान समस्या हल की जो मैं पूरी तरह से कर रहा था, और मुझे कई सिरदर्द बचाया। – APH

संबंधित मुद्दे