2013-08-14 9 views
9

मुझे आशा है कि आप मेरी मदद कर सकते हैं।पंक्तियों को उनके DATEDIFF द्वारा कैसे समूहित करें?

मुझे एचएच_Solution_Audit तालिका में रिकॉर्ड प्रदर्शित करने की आवश्यकता है - यदि 2 या अधिक कर्मचारी 10 मिनट के भीतर कमरे में प्रवेश करते हैं। यहां आवश्यकताएं हैं:

  1. केवल उन ईवेंट को प्रदर्शित करें जिनमें टाइमस्टैम्प (LAST_UPDATED) अंतराल 10 मिनट से कम या उसके बराबर है। इसलिए, मुझे वर्तमान पंक्ति की तुलना अगले पंक्ति और पिछली पंक्ति से तुलना करनी चाहिए ताकि यह जांच सके कि उनके DATEDIFF 10 मिनट से कम या उसके बराबर हैं या नहीं। मैं इस भाग के साथ कर रहा हूँ।
  2. को ही रिकार्ड को दिखाता है कि बराबर या उससे कम करने के लिए 10 मिनट के लिए कमरे के अंदर अलग STAFF_GUID की संख्या कम से कम 2 है

HH_Solution_Audit तालिका विवरण:

  1. आईडी - पीके
  2. STAFF_GUID - कर्मचारी आईडी
  3. LAST_UPDATED - datetime जब एक कर्मचारी एक कमरे में प्रवेश करती

यहां तक ​​कि मुझे अब तक क्या मिला है। यह केवल आवश्यकता # 1 को संतुष्ट करता है।

CREATE TABLE HH_Solution_Audit (
ID INT PRIMARY KEY, 
STAFF_GUID NVARCHAR(1), 
LAST_UPDATED DATETIME 
) 
GO 
INSERT INTO HH_Solution_Audit VALUES (1, 'b', '2013-04-25 9:01') 
INSERT INTO HH_Solution_Audit VALUES (2, 'b', '2013-04-25 9:04') 
INSERT INTO HH_Solution_Audit VALUES (3, 'b', '2013-04-25 9:13') 
INSERT INTO HH_Solution_Audit VALUES (4, 'a', '2013-04-25 10:15') 
INSERT INTO HH_Solution_Audit VALUES (5, 'a', '2013-04-25 10:30') 
INSERT INTO HH_Solution_Audit VALUES (6, 'a', '2013-04-25 10:33') 
INSERT INTO HH_Solution_Audit VALUES (7, 'a', '2013-04-25 10:41') 
INSERT INTO HH_Solution_Audit VALUES (8, 'a', '2013-04-25 11:02') 
INSERT INTO HH_Solution_Audit VALUES (9, 'a', '2013-04-25 11:30') 
INSERT INTO HH_Solution_Audit VALUES (10, 'a', '2013-04-25 11:45') 
INSERT INTO HH_Solution_Audit VALUES (11, 'a', '2013-04-25 11:46') 
INSERT INTO HH_Solution_Audit VALUES (12, 'a', '2013-04-25 11:51') 
INSERT INTO HH_Solution_Audit VALUES (13, 'a', '2013-04-25 12:24') 
INSERT INTO HH_Solution_Audit VALUES (14, 'b', '2013-04-25 12:27') 
INSERT INTO HH_Solution_Audit VALUES (15, 'b', '2013-04-25 13:35') 

DECLARE @numOfPeople INT = 2, 
       --minimum number of people that must be inside 
       --the room for @lengthOfStay minutes 
      @lengthOfStay INT = 10, 
       --number of minutes of stay 
      @dateFrom DATETIME = '04/25/2013 00:00', 
      @dateTo DATETIME = '04/25/2013 23:59'; 
    WITH cteSource AS 
    (
     SELECT ID, STAFF_GUID, LAST_UPDATED, 
       ROW_NUMBER() OVER (ORDER BY LAST_UPDATED) AS row_num 
     FROM HH_SOLUTION_AUDIT 
       WHERE LAST_UPDATED >= @dateFrom AND LAST_UPDATED <= @dateTo 
    ) 
    SELECT [current].ID, [current].STAFF_GUID, [current].LAST_UPDATED 
    FROM 
     cteSource AS [current] 
    LEFT OUTER JOIN 
     cteSource AS [previous] ON [current].row_num = [previous].row_num + 1 
    LEFT OUTER JOIN 
     cteSource AS [next] ON [current].row_num = [next].row_num - 1 
    WHERE 
     DATEDIFF(MINUTE, [previous].LAST_UPDATED, [current].LAST_UPDATED) 
     <= @lengthOfStay 
     OR 
     DATEDIFF(MINUTE, [current].LAST_UPDATED, [next].LAST_UPDATED) 
     <= @lengthOfStay 
    ORDER BY [current].ID, [current].LAST_UPDATED  

क्वेरी रनिंग रिटर्न आईडी:
1, 2, 3, 5, 6, 7, 10, 11, 12, 13, 14
कि पिछली पंक्ति, वर्तमान पंक्ति और अगली पंक्ति के बीच 10 मिनट अंतराल से कम या बराबर होने की आवश्यकता # 1 को संतुष्ट करता है।

क्या आप दूसरी आवश्यकता के साथ मेरी मदद कर सकते हैं? यदि यह लागू की गई लौटे ID केवल तभी किया जाना चाहिए:
13, 14

+4

आप सेटअप कर सकते हैं एक नमूना डेटा? उन पर कुछ पंक्तियां और अपेक्षित परिणाम? –

+2

प्रश्न वास्तव में भगवान है, और मैं देख सकता हूं कि आप वास्तव में कोशिश करते हैं, लेकिन यदि आप कुछ उदाहरण देते हैं तो हम आपकी मदद कर सकते हैं। धन्यवाद! – GianlucaBobbio

+0

@NenadZivkovic हाय नेनाद। मैंने आपके द्वारा अनुरोध किए गए नमूना डेटा और अपेक्षित परिणाम जोड़े। धन्यवाद। मैं उसके बारे में भूल गया। – Raii

उत्तर

3

यहाँ एक विचार है। आपको ROW_NUMBER और पिछले और अगले रिकॉर्ड की आवश्यकता नहीं है। आपको बस संघीय प्रश्न पूछने की ज़रूरत है - कोई ऐसा व्यक्ति ढूंढ रहा है जिसने किसी को X मिनट पीछे चेक किया हो, और दूसरा X मिनट के लिए आगे की तलाश कर रहा हो। मिलान करने वाले लोगों की संख्या खोजने के लिए प्रत्येक एक सहसंबंधित उप-क्वेरी और COUNT (*) का उपयोग करता है। यदि संख्या अधिक है तो आपके @numOfPeople - यही वह है।

संपादित करें: नया संस्करण: 10 मिनट आगे और पीछे के साथ दो प्रश्न करने के बजाय, हम केवल 10 मिनट के लिए जांच करेंगे - सीटीएलस्टोनेस में मेल खाने वाले लोगों का चयन करें। उसके बाद उन 10 मिनटों में वास्तव में मौजूद लोगों की तलाश करने के लिए क्वेरी के दूसरे भाग में जाना होगा। अंत में फिर से उनमें से संघ बनाने और 'आखिरी लोगों'

WITH cteSource AS 
(
    SELECT ID, STAFF_GUID, LAST_UPDATED 
    FROM HH_SOLUTION_AUDIT 
    WHERE LAST_UPDATED >= @dateFrom AND LAST_UPDATED <= @dateTo 
) 
,cteLastOnes AS 
(
    SELECT * FROM cteSource c1 
    WHERE @numOfPeople -1 <= (SELECT COUNT(DISTINCT STAFF_GUID) 
           FROM cteSource c2 
           WHERE DATEADD(MI,@lengthOfStay,c2.LAST_UPDATED) > c1.LAST_UPDATED 
           AND C2.LAST_UPDATED <= C1.LAST_UPDATED 
           AND c1.STAFF_GUID <> c2.STAFF_GUID) 
) 
SELECT * FROM cteLastOnes 
UNION 
SELECT * FROM cteSource s 
WHERE EXISTS (SELECT * FROM cteLastOnes l 
       WHERE DATEADD(MI,@lengthOfStay,s.LAST_UPDATED) > l.LAST_UPDATED 
       AND s.LAST_UPDATED <= l.LAST_UPDATED 
       AND s.STAFF_GUID <> l.STAFF_GUID) 

SQLFiddle DEMO - new version

SQLFiddle DEMO - old version

+0

आपको बहुत धन्यवाद नेनाद! मुझे इसकी सादगी पसंद है! – Raii

+1

@ राई एनपी। आप 'COUNT (*)' 'COUNT (Distist STAFF_GUID)' के साथ प्रतिस्थापित करना चाहेंगे - यह सुनिश्चित करने के लिए कि केवल विशिष्ट स्टाफ सदस्यों की गणना की जाए। इस उदाहरण में अप्रासंगिक है, लेकिन यदि आपके पास '@ numOfPeople' 2 से बड़ा होने के लिए –

+0

नेनाड है, तो यह एक फर्क पड़ सकता है। 'COUNT' में अंतर देखने के लिए मैं आपकी स्क्रिप्ट के चारों ओर खेलूँगा। मुझे इसके तर्क पसंद हैं। इस तरह से अपना काम करने के बारे में नहीं सोचा था। एक बार फिर धन्यवाद। – Raii

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