2012-01-23 14 views
8

में केवल पहला रिकॉर्ड खोजें, मैं सदस्य रिकॉर्ड्स की एक सूची प्रदर्शित करने की कोशिश कर रहा हूं, और मेरे पास कुछ टेबल हैं जो मैं उपयोग करने के लिए उपयोग कर रहा हूं।MySQL सबक्वायरी - बाएं जॉइन

आसान हिस्सा है यही कारण है कि। जिस भाग में मुझे मदद की ज़रूरत है वह उस तालिका के साथ है जिसमें प्रत्येक सदस्य रिकॉर्ड के लिए कई रिकॉर्ड हैं: लॉगिन इतिहास

मैं प्रत्येक सदस्य रिकॉर्ड के लिए केवल पहली पंक्ति प्रदर्शित करना चाहता हूं, जो लॉगिन इतिहास तालिका में मौजूद है। वैकल्पिक रूप से, मैं फ्लॉप फ्लिप और लॉगिन इतिहास तालिका में पिछले रिकॉर्ड प्रदर्शित करने के लिए, साथ ही कर सकते हैं।

यहाँ मैं अब तक क्या कर लिया है:

SELECT m.memberid, m.membername, m.gender, mp.phone 
FROM tbl_members m, 
    tbl_members_phones mp, 
    tbl_members_addresses ma 
WHERE m.defaultphoneid = mp.phoneid 
AND m.defaultaddressid = ma.addressid 

तो रिटर्न कि क्या उम्मीद है।

tbl_members_login_history से 2 कॉलम मैं लौटा परिणाम में जोड़ना चाहता हूं: mh। loggedtime, एमएच। ipaddy

मैं tbl_members_login_history जोड़ने पता एक वाम के रूप में डुप्लिकेट वापसी होगी शामिल हों, तो मैं सोच रहा हूँ एक Subquery आवश्यकता यहाँ वहाँ होना चाहिए ताकि memberid कि tbl_members_login_history में मौजूद है के लिए सिर्फ 1 रिकॉर्ड वापस जाने के लिए है,।

मुझे क्या चिंता है कि अगर इतिहास तालिका में कोई रिकॉर्ड मौजूद नहीं है, तो भी मैं उस सदस्य की जानकारी प्रदर्शित करना चाहता हूं, लेकिन इतिहास कॉलम को न्यूल के रूप में छोड़ दें।

यह एक सबक्वेरी घटना होगा? और यदि हां, तो उस प्रकार के LIMIT को कैसे जोड़ता है?

+0

जिज्ञासा से बाहर, किसी सदस्य के लिए आवश्यक फ़ोन और पता आज़मा सकते हैं? यदि नहीं, तो मुझे नहीं लगता कि आपकी क्वेरी अन्य सदस्य की जानकारी वापस आ जाएगी अगर उनमें से एक तरह से लिखा है याद आ रही है है। – Sam

+0

इस मामले में, हाँ। लेकिन आप सही हैं, सदस्य को मौजूदा रिकॉर्ड के बिना परिणाम में वापस नहीं किया जाएगा। – coffeemonitor

उत्तर

20

यह greatest-n-per-group समस्या है, जिसे अक्सर स्टैक ओवरफ़्लो पर पूछा जाता है।

यहाँ कैसे मैं अपने परिदृश्य में इसे हल करेंगे:

SELECT m.memberid, m.membername, m.gender, mp.phone, mh.loggedtime, mh.ipaddy 
FROM tbl_members m 
INNER JOIN tbl_members_phones mp ON m.defaultphoneid = mp.phoneid 
INNER JOIN tbl_members_addresses ma ON m.defaultaddressid = ma.addressid 
LEFT OUTER JOIN tbl_members_login_history mh ON m.memberid = mh.memberid 
LEFT OUTER JOIN tbl_members_login_history mh2 ON m.memberid = mh2.memberid 
    AND mh.pk < mh2.pk 
WHERE mh2.pk IS NULL; 

है यही कारण है, हम चाहते हैं mh दिया memberid के लिए tbl_member_login_history में सबसे हाल ही पंक्ति किया जाना है। तो हम एक और पंक्ति mh2 भी अधिक हाल ही में है कि के लिए खोज। यदि कोई भी अधिक mh पंक्ति से हाल ही में पाया जाता है, तो mh2.* शून्य हो जाएगा, तो mh सबसे हाल ही में किया जाना चाहिए।

मुझे लगता है कि इस तालिका में प्राथमिक कुंजी कॉलम है जिसमें बढ़ते मूल्य हैं। इस उदाहरण के लिए, मुझे लगता है कि कॉलम नाम pk है।

वाम बाहरी का उपयोग के लिए लॉगिन इतिहास मेज पर दोनों संदर्भ मतलब यह है कि m पंक्ति सूचित किया जाएगा, भले ही वहाँ कोई मिलता-जुलता पंक्ति में शामिल हों।

+0

मैंने अभी आपके समाधान की कोशिश की है और इसे एक क्वेरी में तुलना की है जिसमें 'GROUP BY' का उपयोग करके' MAX (...) 'के साथ 'sub date = maxdate'' में शामिल होने के साथ एक सबक्वायरी है।'<' ऑपरेटर के साथ आपके समाधान ने 2s (!) लिया, जबकि सबक्वायरी समाधान 0.01s (पाठ्यक्रम की एक ही परिणाम तालिका) लिया। आपकी क्वेरी का 'एक्सप्लाइन' सबक्वायरी के मुकाबले ज्यादा बेहतर दिखता है। मुझे नहीं पता कि मुझे यह बड़ा प्रदर्शन अंतर क्यों मिलता है, लेकिन मुझे लगता है कि ऐसा इसलिए है क्योंकि '<' एक विशाल मध्यवर्ती परिणाम उत्पन्न करता है। – steffen

+0

@steffen: हाँ, चूंकि मैंने इस प्रश्न का उत्तर दिया है, मैंने कई अन्य मामलों को देखा है, और निष्कर्ष निकाला है कि या तो ऊपर का समाधान या आपके जैसे समाधान का वर्णन * तेजी से हो सकता है, कितने अलग समूहों और कितने डेटा प्रति पंक्ति पंक्तियों। तो अपने डेटा के साथ दोनों तरीकों का परीक्षण करना और फिर निर्णय लेना सबसे अच्छा है। –

+0

सच है। मुझे क्या उलझन में बड़ा प्रदर्शन अंतर था। मुझे SO पर आपके समाधान को दो बार मिला। और 'EXPLAIN' आउटपुट बहुत अच्छा लग रहा है इसलिए मुझे उम्मीद है कि क्वेरी बहुत तेज होगी। लेकिन इसके बजाय यह बहुत धीमी थी। अजीब। – steffen

0

की तरह इस

LEFT OUTER JOIN (SELECT member_id, MAX(LAST_LOGIN_DATE) from tbl_members_login_history) Last_Login ON Last_Login.memberid = m.memberid 

पुनश्च जोड़ें। LAST_LOGIN_DATE छद्म कॉलम है, आप अपने restictive कॉलम

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