2009-02-11 12 views
49

द्वारा एक समूह द्वारा दिया जाता है मैं इस तरह एक डेटाबेस तालिका है:MySQL - नियंत्रण जो पंक्ति

id version_id field1 field2 
1  1    texta  text1 
1  2    textb  text2 
2  1    textc  text3 
2  2    textd  text4 
2  3    texte  text5 

आप इसे बाहर काम नहीं किया है, तो यह एक पंक्ति के संस्करणों की एक संख्या में शामिल हैं, और उसके बाद कुछ पाठ डेटा।

मैं इसे पूछना चाहता हूं और प्रत्येक आईडी के लिए संस्करण को उच्चतम संख्या के साथ वापस करना चाहता हूं। (इसलिए उपरोक्त में केवल दूसरी और आखिरी पंक्तियां)।

मैंने संस्करण_आईडी डीईएससी द्वारा ऑर्डर करते समय समूह का उपयोग करने का प्रयास किया है - लेकिन ऐसा लगता है कि इसके समूह के बाद ऑर्डर करना है, इसलिए यह काम नहीं करता है।

किसी को भी कोई विचार है? मुझे विश्वास नहीं है कि यह नहीं किया जा सकता है!

अद्यतन:

इस है, जो काम करता है के साथ आते हैं, लेकिन एक सबक्वेरी उपयोग करता है:

SELECT * 
FROM (SELECT * FROM table ORDER BY version_id DESC) t1 
GROUP BY t1.id 
+0

संबंधित: http://stackoverflow.com/questions/13700456/mysql-group-by-implementation-details-which-row-mysql-chooses-in-a-group-by-qu – ripper234

उत्तर

44

यह एक स्तंभ के समूह के लिहाज से अधिकतम का चयन कहा जाता है। Here are several different approaches for mysql.

यहाँ कैसे मैं यह कर देगा:

SELECT * 
FROM (SELECT id, max(version_id) as version_id FROM table GROUP BY id) t1 
INNER JOIN table t2 on t2.id=t1.id and t1.version_id=t2.version_id 

यह अपेक्षाकृत कुशल हो जाएगा, हालांकि mysql सबक्वेरी के लिए स्मृति में अस्थायी तालिका का निर्माण करेगा। मुझे लगता है कि इस तालिका के लिए आपके पास पहले से ही एक आईडी (id, version_id) है।

यह एसक्यूएल में कमी है कि आपको इस प्रकार की समस्या के लिए कम से कम एक सबक्वायरी का उपयोग करना होगा (semi-joins एक और उदाहरण है)।

सबक्वायरीज़ को mysql में अच्छी तरह से अनुकूलित नहीं किया गया है, लेकिन जब तक वे इतना विशाल नहीं हैं कि वे स्मृति के बजाय डिस्क पर लिखे जाएंगे, तो असुरक्षित सबक्विरी इतनी खराब नहीं हैं। यह देखते हुए कि इस प्रश्न में केवल दो इन्ट्स हैं, उपरोक्त होने से पहले लाखों पंक्तियां हो सकती हैं लेकिन आपकी पहली क्वेरी में चयन * सबक्वायरी इस समस्या से बहुत जल्द पीड़ित हो सकती है।

+3

लिंक किया गया लेख बहुत है अच्छा! लिंक के लिए – onnodb

+0

ता, और उदाहरण। हम सबक्वायरी विकल्प के साथ जा रहे हैं। लिंक किए गए आलेख के लिए – benlumley

+0

+1। धन्यवाद। – dotancohen

3

मुझे लगता है कि यह ऐसा करेगा, सुनिश्चित नहीं है कि यह सबसे अच्छा या सबसे तेज़ है या नहीं।

चयन आईडी, version_id, फ़ील्ड 1, field2 डीटी के रूप में datatable से:

SELECT * FROM table 
WHERE (id, version_id) IN 
    (SELECT id, MAX(version_id) FROM table GROUP BY id) 
+0

मैं गलत हो सकता हूं, लेकिन ऐसा लगता है क्योंकि प्रत्येक पंक्ति के लिए सबक्वायरी निष्पादित की जाएगी और फिर परीक्षण किया जाएगा (हालांकि कुछ कैशिंग हो सकती है) ... क्या यह सच है? – Buksy

+0

यह बेहद असंभव है, यह सबसे अधिक संभावना है कि सबक्वायरी के परिणामों के साथ एक अस्थायी तालिका बनाएं और उनसे तुलना करें। हालांकि मैं सभी डेटाबेस सिस्टम के लिए बात नहीं कर सकता। –

0

यह छद्म कोड लेकिन कुछ इस तरह ठीक काम करना चाहिए

select * 
from table 
inner join 
(
    select id , max(version_id) maxVersion 
    from table 
) dvtbl ON id = dvtbl.id && versionid = dvtbl.maxVersion 
0

मैं आमतौर पर एक सबक्वेरी के साथ ऐसा है जहां id = (datatable से आईडी का चयन करें जहां id_ dt.id ऑर्डर संस्करण_आईडी desc सीमा 1)

-1

मुझे लगता है कि यह वही है जो आप चाहते हैं।

select id, max(v_id), field1, field2 from table group by id 

परिणाम मुझे लगता है कि कर रहे हैं से

1, 2, textb मिलता है, टेक्स्ट 2

2, 3, texte, text5

संपादित करें: मैं तालिका को फिर से बनाया और आईडी के साथ एक ही डेटा डालें एक संस्करण_आईडी एक यौगिक प्राथमिक कुंजी है। इसने उत्तर दिया जो मैंने पहले प्रदान किया था। यह MySQL में भी था।

+0

जो काम नहीं करता है, इसलिए सवाल - समूह द्वारा समूह में संस्करण के लिए अधिकतम के साथ, समूह में पहली पंक्ति होने वाली समूह वापस आ जाएगी। – benlumley

+0

कोई भी काम नहीं करता है ... मैंने उस तालिका को फिर से बनाया जब उसने क्वेरी चलाई और यह ठीक काम करता था। –

+0

@ बेरेक: 'फ्रैड नहीं। "[सर्वर प्रत्येक समूह से कोई भी मूल्य चुनने के लिए स्वतंत्र है, इसलिए जब तक वे समान नहीं होते हैं, तो चुने गए मान अनिश्चित हैं। \ [.. \] कुछ मामलों में, आप MIN() और MAX() को प्राप्त करने के लिए उपयोग कर सकते हैं विशिष्ट ** कॉलम ** मान भी अगर यह अद्वितीय नहीं है।] (http://dev.mysql.com/doc/refman/5.0/en/group-by-hidden-columns.html) " –

2
SELECT id, version_id, field1, field2 
FROM (
    SELECT @prev = id AS st, (@prev := id), m.* 
    FROM (
      (SELECT @prev := NULL) p, 
      (
      SELECT * 
      FROM mytable 
      ORDER BY 
        id DESC, version_id DESC 
      ) m 
    ) m2 
WHERE NOT IFNULL(st, FALSE); 

नहीं सबक्वेरी, UNIQUE INDEX ON MYTABLE (id, version_id) पर एक पास यदि आपके पास एक (जो मुझे लगता है कि आप चाहिए)

-2

यह परीक्षण नहीं किया है, लेकिन कुछ इस तरह काम कर सकते हैं:

चुनें * मेज ग्रुप से ID द्वारा द्वारा मैक्स (version_id) DESC आदेश

0

इस क्वेरी से एक समूह के बिना काम करेगा:

SELECT * FROM table AS t 
LEFT JOIN table AS t2 
    ON t.id=t2.id 
    AND t.version_id < t2.version_id 
WHERE t2.id IS NULL 

इसे किसी भी अस्थायी तालिकाओं की आवश्यकता नहीं है।

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