2012-02-24 16 views
12

समस्या:
मेरे पास एक सारणी है जो foo में डेटा पंक्तियों को रिकॉर्ड करती है। प्रत्येक बार पंक्ति अद्यतन होने पर, एक संशोधन संख्या के साथ एक नई पंक्ति डाली जाती है। तालिका इस तरह दिखती है:कई समूहों के लिए रिकॉर्ड के प्रत्येक समूह में सबसे हालिया और विशिष्ट संस्करण का चयन करना

id rev field 
1 1 test1 
2 1 fsdfs 
3 1 jfds 
1 2 test2 

ध्यान दें कि तालिका में अंतिम रिकॉर्ड पहली पंक्ति का एक नया संस्करण है।

क्या किसी को पंक्तियों के नवीनतम संस्करण के लिए पूछने के लिए एक कुशल तरीका पता है, रिकॉर्ड के एक विशिष्ट संस्करण का उत्तर दें? उदाहरण के लिए, rev=2 के लिए एक क्वेरी 2, 3 और चौथी पंक्ति (हालांकि पहली पंक्ति को प्रतिस्थापित नहीं किया गया है) लौटाएगी जबकि rev=1 के लिए एक क्वेरी < = 1 के साथ उन पंक्तियों को उत्पन्न करती है और डुप्लीकेट आईडी के मामले में, उच्च संशोधन वाले व्यक्ति संख्या चुना जाता है (रिकॉर्ड: 1, 2, 3)।

मैं वास्तव में यकीन है कि अगर यह एसक्यूएल सर्वर में भी संभव है नहीं कर रहा हूँ ...

मैं एक सतत तरह से परिणाम वापस जाने के लिए पसंद करते हैं नहीं होगा।

+0

एसक्यूएल सर्वर किस संस्करण का उपयोग कर रहे हैं? –

+0

एमएस एसक्यूएल 2008 आर 2, लेकिन आदर्श रूप में मैं एक क्वेरी जेनरेट करना चाहता हूं जो किसी भी एसक्यूएल सर्वर विनिर्देशों पर निर्भर नहीं है। – orange

+0

इस प्रश्न को 'रिकर्सन' और 'आरसीएस' के रूप में क्यों टैग किया गया है? –

उत्तर

28

केवल नवीनतम संशोधन प्राप्त करने के लिए:

SELECT * from t t1 
WHERE t1.rev = 
    (SELECT max(rev) FROM t t2 WHERE t2.id = t1.id) 

इस मामले 1 में एक विशिष्ट संशोधन करने के लिए, (और एक आइटम संशोधन अभी तक अगले सबसे छोटा संशोधन नहीं करने पर):

SELECT * from foo t1 
WHERE t1.rev = 
    (SELECT max(rev) 
    FROM foo t2 
    WHERE t2.id = t1.id 
    AND t2.rev <= 1) 

यह ऐसा करने का सबसे प्रभावी तरीका नहीं हो सकता है, लेकिन अभी मैं इसे करने का बेहतर तरीका नहीं समझ सकता।

+0

उत्तर के लिए धन्यवाद। यह अच्छी तरह से काम करता है। आपको ऐसा क्यों लगता है कि यह अक्षम है? नेस्टेड क्वेरी के कारण – orange

+1

। मूल रूप से टी में प्रत्येक पंक्ति के लिए आपको दूसरी क्वेरी करना है। – Tim

+2

@Tim - सच नहीं है। एसक्यूएल घोषणात्मक नहीं है। इस मामले में SQL सर्वर इस पैटर्न को जानता है और योजना आश्चर्यजनक रूप से सरल है। [योजना छवि] (http://i.stack.imgur.com/MUb0m.jpg) –

4

आप प्रत्येक क्षेत्र के सभी नवीनतम संशोधन चाहते हैं, आप अपने उदाहरण के मामले में

SELECT C.rev, C.fields FROM (
    SELECT MAX(A.rev) AS rev, A.id 
    FROM yourtable A 
    GROUP BY A.id) 
AS B 
INNER JOIN yourtable C 
ON B.id = C.id AND B.rev = C.rev 

उपयोग करते हैं, कि

rev field 
1 fsdfs 
1 jfds 
2 test2 
+0

या तो कॉलम "ए" या उपयोगकर्ता परिभाषित फ़ंक्शन या कुल "एएमएक्स" नहीं ढूंढ सकता है, या नाम संदिग्ध है। यह त्रुटि संदेश आता है, लेकिन यह मुझे बहुत मदद नहीं करता है ... – orange

+0

आपको MAX से पहले ए की आवश्यकता नहीं है, बस इस तरह अधिकतम उपयोग करें: MAX (A.rev) या max (rev) – Tim

+0

ओप्स , मेरी गलती! क्वेरी को सही किया। – Treb

1
SELECT foo.* from foo 
left join foo as later 
on foo.id=later.id and later.rev>foo.rev 
where later.id is null; 
4

वापसी होगी यह वह जगह है सकते हैं मैं कैसे होगा कर दो। ROW_NUMBER() एसक्यूएल सर्वर की आवश्यकता है 2005 या उसके बाद

नमूना डेटा:

DECLARE @foo TABLE (
    id int, 
    rev int, 
    field nvarchar(10) 
) 

INSERT @foo VALUES 
    (1, 1, 'test1'), 
    (2, 1, 'fdsfs'), 
    (3, 1, 'jfds'), 
    (1, 2, 'test2') 

क्वेरी:

DECLARE @desiredRev int 

SET @desiredRev = 2 

SELECT * FROM (
SELECT 
    id, 
    rev, 
    field, 
    ROW_NUMBER() OVER (PARTITION BY id ORDER BY rev DESC) rn 
FROM @foo WHERE rev <= @desiredRev 
) numbered 
WHERE rn = 1 

भीतरी SELECT रिटर्न सभी प्रासंगिक रिकॉर्ड, और प्रत्येक id समूह के भीतर (कि PARTITION BY है), rev अवरोही द्वारा आदेशित पंक्ति संख्या की गणना करता है।

बाहरी SELECT प्रत्येक id समूह से पहले सदस्य (इसलिए, उच्चतम rev वाला) का चयन करता है।

आउटपुट जब @desiredRev = 2:

id   rev   field  rn 
----------- ----------- ---------- -------------------- 
1   2   test2  1 
2   1   fdsfs  1 
3   1   jfds  1 

आउटपुट जब @desiredRev = 1:

id   rev   field  rn 
----------- ----------- ---------- -------------------- 
1   1   test1  1 
2   1   fdsfs  1 
3   1   jfds  1 
+0

ठीक काम करने लगता है। मुझे पसंद है कि आप आसानी से संशोधन संख्या का चयन कर सकते हैं। हालांकि, यदि संभव हो तो मैं एक सादे एसक्यूएल क्वेरी पसंद करूंगा। – orange

2
SELECT 
    MaxRevs.id, 
    revision.field 
FROM 
    (SELECT 
    id, 
    MAX(rev) AS MaxRev 
    FROM revision 
    GROUP BY id 
) MaxRevs 
    INNER JOIN revision 
    ON MaxRevs.id = revision.id AND MaxRevs.MaxRev = revision.rev 
+0

भी एक विशिष्ट संशोधन का चयन करने के लिए:। चयन संशोधन * से ( आईडी, मैक्स (राजस्व) का चयन MaxRev के रूप में संशोधन से जहां राजस्व <= 2 ग्रुप आईडी द्वारा) MaxRevs अंदरूनी संशोधन शामिल हों MaxRevs.id = revision.id और MaxRevs.MaxRev = revision.rev पर – Mahe

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