2012-06-12 12 views
31

चलो कहते हैं कि मैं एक मेज कॉलम के साथ messages कहा जाता है दो:ग्रुप BY का उपयोग करके प्रत्येक समूह में नवीनतम रिकॉर्ड कैसे प्राप्त करें?

id | from_id | to_id | subject | message | timestamp 

मैं केवल प्रत्येक उपयोगकर्ता से नवीनतम संदेश प्राप्त करने, जैसे आप अपने फेसबुक इनबॉक्स में देखना होगा इससे पहले कि आप वास्तविक धागा में अंदर घुसते हैं चाहता हूँ।

इस क्वेरी मुझे परिणाम मैं जरूरत के करीब लगता है:

SELECT * FROM messages GROUP BY from_id 

हालांकि क्वेरी मुझे प्रत्येक उपयोगकर्ता और नहीं नए से सबसे पुराने संदेश दे रहा है।

मैं इसे एक नहीं समझ सकता।

+0

भी इस समस्या [यहां] (करने के लिए एक बेहतर समाधान है http://stackoverflow.com/questions/1313120/retrieving-the-last- रिकॉर्ड-इन-प्रत्येक-समूह) –

उत्तर

74

आप प्रत्येक समूह (सबक्वेरी) में पिछले timestamp मूल्यों का पता लगाना चाहिए और फिर तालिका में यह सबक्वेरी में शामिल होने के -

SELECT t1.* FROM messages t1 
    JOIN (SELECT from_id, MAX(timestamp) timestamp FROM messages GROUP BY from_id) t2 
    ON t1.from_id = t2.from_id AND t1.timestamp = t2.timestamp; 
+4

+1 एक आम समस्या है लेकिन समूह में नहीं चुनने वाले कॉलम को अनुमति देने की अनुमति देने के लिए MySQLs सुविधा का उपयोग न करने के लिए आपको बहुत बहुत धन्यवाद! – GarethD

+0

आपको बहुत धन्यवाद! मैं बिना किसी समस्या के अतिरिक्त टेबल में शामिल होने में सक्षम था। इतना अच्छा दृष्टिकोण। – user1019144

+0

यह बिल्कुल सही है। – enchance

-4

आपको उन्हें ऑर्डर करने की आवश्यकता है।

SELECT * FROM messages GROUP BY from_id ORDER BY timestamp DESC LIMIT 1

+0

शीर्ष (1) * .... – BumbleB2na

+0

@ BumbleB2na 'LIMIT 1' का मतलब है? – Li0liQ

+0

अब आपको सभी संदेशों का अंतिम संदेश मिलेगा, आपको एक शर्त की आवश्यकता है जहां – jcho360

1

यह एक मानक समस्या है।

ध्यान दें कि MySQL आपको ग्रुप बाय क्लॉज से कॉलम को छोड़ने की अनुमति देता है, जो मानक एसक्यूएल नहीं करता है, लेकिन जब आप MySQL सुविधा का उपयोग करते हैं तो आपको सामान्य रूप से निर्धारिती परिणाम नहीं मिलते हैं।

SELECT * 
    FROM Messages AS M 
    JOIN (SELECT To_ID, From_ID, MAX(TimeStamp) AS Most_Recent 
      FROM Messages 
     WHERE To_ID = 12345678 
     GROUP BY From_ID 
     ) AS R 
    ON R.To_ID = M.To_ID AND R.From_ID = M.From_ID AND R.Most_Recent = M.TimeStamp 
WHERE M.To_ID = 12345678 

मैं मैच के लिए क्या आप होने की संभावना हो To_ID पर एक फिल्टर जोड़ दिया है। क्वेरी इसके बिना काम करेगी, लेकिन सामान्य रूप से बहुत अधिक डेटा लौटाएगी। स्थिति को नेस्टेड क्वेरी और बाहरी क्वेरी दोनों में वर्णित करने की आवश्यकता नहीं है (ऑप्टिमाइज़र को स्वचालित रूप से स्थिति को धक्का देना चाहिए), लेकिन यह दिखाए गए अनुसार शर्त को दोहराने के लिए कोई नुकसान नहीं हो सकता है।

+0

नवीनतम मानक एसक्यूएल आपको कॉलम को छोड़ने की अनुमति देता है 'ग्रुप बाय' और उन्हें 'चयन' या 'हैविंग' खंड में शामिल करें, बशर्ते वे 'ग्रुप बाय' संयोजन पर कार्यात्मक रूप से निर्भर हों - और इस प्रकार केवल निर्धारिती परिणाम लौटाए जाएंगे। (MySQL पाठ्यक्रम की ऐसी कोई जांच नहीं करता है।) –

+0

@ypercube यह सुनिश्चित नहीं है कि यह इसके लिए जगह है, लेकिन क्या आपके पास इसके लिए कोई अच्छा लिंक है। मैं अपने सिर को इस बारे में नहीं समझ सकता कि समूह में नहीं होने वाले कॉलम का चयन करके समूह में वस्तुओं पर निर्भर होने के आधार पर निर्धारक बन सकता है, एकमात्र तरीका जिसे मैं इसे निर्धारित करने के लिए देख सकता हूं, आदेश के उपयोग के माध्यम से होता है। हालांकि उदाहरण देखने से चीजों को स्पष्ट करने में मदद मिल सकती है। धन्यवाद – GarethD

+0

'ग्रुप बाय पीके' एक साधारण उदाहरण होगा। मेरा जवाब [यहां] (http://stackoverflow.com/questions/7594865/why-does-mysql-add-a-feature-that-conflicts-with-sql-standards/7596265#7596265) से लिंक है (एक प्रति के) मानक। –

2

बस के पूरक क्या Devart कहा प्रश्न के अनुसार, नीचे दिए गए कोड आदेश देने नहीं है:

SELECT t1.* FROM messages t1 
    JOIN (SELECT from_id, MAX(timestamp) timestamp FROM messages GROUP BY from_id) t2 
    ON t1.from_id = t2.from_id AND t1.timestamp = t2.timestamp; 

खंड "द्वारा समूह" उस के बाद से मुख्य क्वेरी में होना चाहिए हम की जरूरत पहले से "SOURCE" को पुन: व्यवस्थित

SELECT t1.* FROM messages t1 
    JOIN (SELECT from_id, MAX(timestamp) timestamp FROM messages ORDER BY timestamp DESC) t2 
    ON t1.from_id = t2.from_id AND t1.timestamp = t2.timestamp GROUP BY t2.timestamp; 

सादर,

12

इस

का प्रयास करें: जरूरत "समूह" इतना पाने के लिए हर Form_id के लिए
SELECT * FROM messages where id in (SELECT max(id) FROM messages GROUP BY from_id) order by id desc 
+3

हालांकि यह कोड प्रश्न का उत्तर दे सकता है, लेकिन कुछ _context_ को शामिल करना बेहतर होगा, _how_ यह बताता है और इसका उपयोग करने के लिए _when_। कोड-केवल उत्तर लंबे समय तक उपयोगी नहीं होते हैं। –

+0

"संदेशों से ग्रुप (आईडी) से समूह" इस आंतरिक क्वेरी से, यह पहले उपयोगकर्ता (from_id) द्वारा रिकॉर्ड/संदेश समूहबद्ध करता है और फिर अधिकतम रिकॉर्ड आईडी खींचता है। फिर हम आंतरिक क्वेरी परिणाम सेट से केवल नवीनतम रिकॉर्ड/संदेश प्राप्त करने के लिए संदेश तालिका पर फिर से पूछताछ कर रहे हैं। –

+0

सबसे आसान समाधान IMHO – Nowdeen

2

इस क्वेरी वापसी पिछले रिकॉर्ड:

SELECT m1.* 
    FROM messages m1 LEFT JOIN messages m2 
    ON (m1.Form_id = m2.Form_id AND m1.id < m2.id) 
    WHERE m2.id IS NULL; 
+0

ईमानदारी से यह उत्तर अनुचित है। यह एकमात्र समाधान था जो मेरे लिए अच्छा काम करता था क्योंकि मैं अपने ऑटो वृद्धि क्षेत्र के अलावा एक अलग क्षेत्र द्वारा समूहित कर रहा हूं, और मुझे नवीनतम तिथि चुननी है। –

+0

इस उत्तर ने मुझे हाइबरनेट एचक्यूएल के साथ काम करने में मदद की। अन्य उत्तरों में से कोई भी काम नहीं करता है, क्योंकि हाइबरनेट केवल कहां और चयन के बाद सबक्वायरी का समर्थन करता है। चूंकि यह उत्तर किसी भी सबक्वायरीज़ का उपयोग नहीं करता है, यह ठीक काम करता है। – Alex

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