2013-01-02 13 views
18

के बिना एक एकल SQL तालिका में डेटा विलय करना मेरे पास एक आईडी कॉलम वाला एक टेबल है और एक संख्या के साथ एक और कॉलम है। एक आईडी में कई संख्याएं हो सकती हैं। उदाहरण के लिएएक कर्सर

ID | Number 
1 | 25 
1 | 26 
1 | 30 
1 | 24 
2 | 4 
2 | 8 
2 | 5 

अब इस डेटा के आधार पर, एक नई तालिका में, मैं इस

ID | Low | High 
1 | 24 | 26 
1 | 30 | 30 
2 | 4 | 5 
2 | 8 | 8 

के लिए आप देख सकते हैं, मैं किसी भी डेटा जहां संख्या लगातार कर रहे हैं मर्ज करने के लिए, की तरह चाहते हैं 24, 25, 26. तो अब कम 24 था, उच्च 26 था, और फिर 30 अभी भी एक अलग सीमा है। मैं बड़ी मात्रा में डेटा से निपट रहा हूं, इसलिए मैं प्रदर्शन के लिए एक कर्सर का उपयोग नहीं करना चाहूंगा (जो मैं पहले कर रहा था, और चीजों को धीमा कर रहा था) ... इसे प्राप्त करने का सबसे अच्छा तरीका क्या है ? मैं कोई एसक्यूएल समर्थक नहीं हूं, इसलिए मुझे यकीन नहीं है कि कोई फ़ंक्शन उपलब्ध है जो इसे आसान बना सकता है, या इसे पूरा करने का सबसे तेज़ तरीका क्या होगा।

सहायता के लिए धन्यवाद।

+3

क्या RDBMS प्रयोग कर रहे हैं? – Taryn

+0

क्षमा करें, मैंने प्रश्न में एक और टैग जोड़ा। यह SQL Server 2008 है। –

+0

लगभग वही: [अनुक्रम पर आधारित परिणामों को समूहबद्ध करने के लिए SQL क्वेरी] (http://stackoverflow.com/questions/5087864/sql-query-for-grouping-the-results-based-on -sequence)। –

उत्तर

36

मुख्य अवलोकन यह है कि संख्याओं का एक अनुक्रम एक अनुक्रम एक स्थिर है। हम row_number का उपयोग कर एक और अनुक्रम उत्पन्न कर सकते हैं। यह सभी समूहों की पहचान करता है:

select id, MIN(number) as low, MAX(number) as high 
from (select t.*, 
      (number - ROW_NUMBER() over (partition by id order by number)) as groupnum 
     from t 
    ) t 
group by id, groupnum 

शेष केवल एकत्रीकरण है।

0

मैं कर्सर के बजाय तालिका चर के साथ WHILE लूप संरचना का उपयोग करने का सुझाव दूंगा।

उदाहरण के लिए, CTE और प्रत्यावर्तन के साथ

DECLARE @TableVariable TABLE 
(
    MyID int IDENTITY (1, 1) PRIMARY KEY NOT NULL, 
    [ID] int, 
    [Number] int 
) 

DECLARE @Count int, @Max int 

INSERT INTO @TableVariable (ID, Number) 
SELECT ID, Number 
FROM YourSourceTable 

SELECT @Count = 1, @Max = MAX(MyID) 
FROM @TableVariable 

WHILE @Count <= @Max 
BEGIN 

    ...do your processing here... 


    SET @Count = @Count + 1 

END 
+0

क्या? नहीं; एसक्यूएल में लूप लगभग हमेशा गलत काम करते हैं। एसक्यूएल को सेट लॉजिक के साथ दिमाग में डिजाइन किया गया था, और इसका लाभ लेने के लिए लिखित रूप में कार्यान्वयन आमतौर पर सबसे अधिक प्रदर्शनकारी होगा। मुझे यह भी लगता है कि इस प्रकार का 'व्हाइली' लूप एक ही अंतर्निहित प्रक्रियाओं को कर्सर के रूप में उपयोग करेगा, जो आपको पहले की तरह खराब स्थान पर छोड़ देगा। इसके अलावा, आपने '@ count' को रीसेट करने के लिए आवश्यक शर्तें नहीं दिखायी हैं ... –

+1

तालिका चर के साथ संयोजन में ऐसे कई मामले सामने आए हैं जहां प्रदर्शन लाभ इसके लायक हैं। इस मामले में 'काउंटर' को रीसेट करने की आवश्यकता नहीं होगी, केवल तालिका चर में प्रत्येक रिकॉर्ड संसाधित होने के कारण बढ़ी है, हालांकि यह ओपी की आवश्यकताओं के आधार पर बदल सकता है। –

3

समाधान:

WITH CTE AS (
    SELECT T.ID, T.NUMBER, T.NUMBER AS GRP 
    FROM T 
    LEFT OUTER JOIN T T2 ON T.ID = T2.ID AND T.NUMBER -1 = T2.NUMBER 
    WHERE T2.ID IS NULL 
    UNION ALL 
    SELECT T.ID, T.NUMBER, GRP 
    FROM CTE 
    INNER JOIN T 
    ON T.ID = CTE.ID AND T.NUMBER = CTE.NUMBER + 1 
) 
SELECT ID, MAX(NUMBER), MIN(NUMBER) 
FROM CTE 
GROUP BY ID, GRP 

Results at fiddlesql