2016-02-24 7 views
5

यह एक बहुत ही आम मामला है, लेकिन मुझे यकीन नहीं है कि मैं कुछ गलत कर रहा हूं।नवीनतम डेटा समूह द्वारा बिना किसी सबक्वायरी

TABLE POSTS [ ID, USER_ID, TOPIC_ID, TIME ] 

मैं topic_id '1'

SELECT p.* 
FROM 
    posts p, 
    (
    SELECT user_id, max(time) mtime 
    FROM  posts 
    WHERE topic_id = 1 
    GROUP BY user_id 
) pm 
WHERE 
    p.user_id = pm.user_id AND 
    p.time = pm.mtime 

यह सही है पर प्रत्येक उपयोगकर्ता द्वारा केवल पिछले पोस्ट प्राप्त करना चाहते हैं? सबकुरी के बिना ऐसा करने का कोई तरीका है?

क्या इस डेटा को वसंत-डेटा प्रश्नों के साथ प्राप्त करने का कोई विकल्प है, या यह केवल एक जेडीबीसी/संग्रहित प्रक्रिया है?

+3

यह सही है - लेकिन हमेशा स्पष्ट जॉइन सिंटैक्स – Strawberry

+1

आह का उपयोग करें, मैंने बहुत जल्द बात की। आपको subquery के SELECT में user_id को शामिल करने की आवश्यकता है, और सर्वोत्तम अभ्यास यह निर्देश देता है कि आपको * ग्रुप BY में topic_id शामिल करना चाहिए (हालांकि यह इस मामले में कड़ाई से जरूरी नहीं है) – Strawberry

+0

हाँ, मैंने अपने डोमेन से "पोस्ट" में अनुवाद को गड़बड़ कर दिया थोड़ा सा, यह "topic_id" के बजाय "user_id" अधिकतम (समय) "होना चाहिए - संपादित – qzshard

उत्तर

1

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

SELECT p.* 
FROM posts p 
LEFT OUTER JOIN posts t 
ON(p.user_id = t.user_id and p.time < t.time and t.topic_id = 1) 
WHERE p.topic_id = 1 and t.topic_id is null 
+0

यह बहुत दिलचस्प है, मैं ' यह अभी तक "चाल" नहीं देखा। हालांकि, यह सभी उपयोगकर्ताओं द्वारा किसी भी विषय पर अंतिम पोस्ट प्राप्त करता है, विषय '1' पर नहीं - क्या परिणाम फ़िल्टर करने का कोई तरीका है? – qzshard

+0

@qzshard हाँ, निश्चित रूप से, ऑन क्लॉज के अंदर, उत्तर अपडेट किया गया .. यदि यह आपकी मदद करता है तो मैं एक अपवॉट (^) और अनुमोदन (वी) – sagi

+0

पुराना स्कूल की सराहना करता हूं। अच्छा है, लेकिन ध्यान दें कि यह विधि अच्छी तरह से स्केल नहीं करती है (ओपी के अपने समाधान के विपरीत) – Strawberry

0

बिना किसी सबक्वायरी के इसे करने के लिए, HAVING का उपयोग करें।

SELECT user_id, topic_id, time 
FROM  posts 
WHERE topic_id = 1 
GROUP BY user_id 
HAVING time = max(time) 
+0

' HAVING समय = .. 'क्या यह 'MySQL' –

+0

में अनुमति नहीं है, लेकिन मैंने कल्पना की है: https: //dev.mysql.com/doc/refman/5.0/en/group-by-handling.html – user1717259

+0

काम नहीं करता है, आप एक पंक्ति पंक्ति संदर्भ में "होने" का उपयोग नहीं कर सकते हैं – qzshard

1

यकीन है कि यहाँ sub-query से बचने के लिए कैसे नहीं हूँ लेकिन एक और तरीका यह है

हो जाएगा
SELECT p.* 
FROM posts p 
WHERE p.time = (SELECT Max(time) mtime 
       FROM posts pm 
       WHERE pm.topic_id = 1 
         AND p.user_id = pm.user_id) 

विंडो फ़ंक्शन Row_number ऐसे मामलों में दुर्भाग्य सेबहुत उपयोगी होगा

+0

धन्यवाद, यह एक और तरीका है जिसे मैंने अन्य प्रश्नों में देखा है। लेकिन प्रदर्शन के संदर्भ में, क्या यह एक बहुत ही गहन सवाल नहीं है (मूल की तुलना में)? – qzshard

+0

@ qzshard- आप अपने वास्तविक समय डेटा के साथ इसका परीक्षण कर सकते हैं –

0

एक अन्य समाधान जो उप क्वेरी से बचाता है (लेकिन फिर भी तेज़ नहीं हो सकता है) substring_index का उपयोग करके प्रत्येक फ़ील्ड के लिए अवरोही के समय के अनुसार आदेश दिया गया है, और फिर SUBSTRING_INDEX का उपयोग करके केवल पहली प्रविष्टि को पकड़ने के लिए SUBSTRING_INDEX द्वारा लौटाया गया।

SELECT user_id, 
    SUBSTRING_INDEX(GROUP_CONCAT(`id` ORDER BY `time` DESC), ',', 1), 
    SUBSTRING_INDEX(GROUP_CONCAT(`topic_id` ORDER BY `time` DESC), ',', 1), 
    SUBSTRING_INDEX(GROUP_CONCAT(`time` ORDER BY `time` DESC), ',', 1) 
FROM posts 
WHERE topic_id = 1 
GROUP BY user_id 
संबंधित मुद्दे