2012-05-04 10 views
7

के परिणामस्वरूप ऑर्डर करना मेरे पास एक प्रश्न है जहां मैं उन सभी उपयोगकर्ताओं को चुनना चाहता हूं जो कलाकारों के दिए गए सेट को पसंद करते हैं। देश पर कुछ अन्य WHERE मानदंड भी हैं। यहां स्कीमा कैसा दिखता है।पोस्टग्रेस्क्ल क्वेरी - सबक्वायरी

  users      favourite_artists    artists 

+----------+------------+ +-----------+------------+ +--------+--------+ 
| id | country | | user_id | artist_id | | id | name | 
+----------+------------+ +-----------+------------+ +--------+--------+ 
|  1 |  gb  | |  1  |  6  | | 1 | Muse | 
|  2 |  gb  | |  1  |  5  | | 2 | RATM | 
|  3 |  us  | |  1  |  3  | | 3 | ABBA | 
|  4 |  us  | |  2  |  3  | | 4 | U2 | 
+----------+------------+ +-----------+------------+ +--------+--------+ 

मैं उन्हें उन कलाकारों की संख्या से आदेश देना चाहता हूं। मैं उन उपयोगकर्ताओं को भी शामिल करना चाहता हूं जो किसी भी कलाकार को पसंद नहीं करते हैं लेकिन WHERE मानदंडों से मेल खाते हैं। अपेक्षित परिणाम सेट जैसा दिखता है।

+--------+---------------+----------------+ 
| id | country | match_count | 
+--------+---------------+----------------+ 
| 6 |  gb  |  4  | 
| 9 |  gb  |  4  | 
| 2 |  gb  |  3  | 
| 1 |  gb  |  2  | 
| 5 |  gb  |  0  | 
| 4 |  gb  |  0  | 
+--------+---------------+----------------+ 

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

SELECT users.id, users.country 
    (SELECT COUNT(*) FROM favourite_artists 
    WHERE user_id = users.id AND artist_id IN (1,3,4,9)) AS match_count   
    FROM "users" 
    WHERE users.country = 'gb' 
    ORDER BY match_count DESC; 

मैं पोस्टग्रेस्क्ल 9.0.7 का उपयोग कर रहा हूं। कोई विचार?

उत्तर

6

आपकी क्वेरी users में प्रत्येक पंक्ति के लिए एक सबक्वायरी निष्पादित कर रही है। इस तरह के प्रश्नों को "सहसंबंधित उपक्वियर" कहा जाता है और उनका प्रदर्शन काफी समझ में आता है।

इसके बजाय यदि आप एक में शामिल होने के लिए चाहते हैं:

SELECT users.id, users.country, count(artist_id) as match_count 
FROM users 
LEFT JOIN favourite_artists ON user_id = users.id AND artist_id IN (1,3,4,9) 
WHERE users.country = 'gb' 
GROUP BY 1, 2 
ORDER BY 3 DESC; 

इस क्वेरी में शामिल होने पंक्तियों में कहीं अधिक कुशलता से मिल जाएगा, यह मानते हुए आप favourite_artists(user_id) पर एक सूचकांक है - या बेहतर अभी तक एक multi-column indexfavourite_artists(user_id, artist_id)। बहुत अच्छे परिचय के लिए

+1

+1। :) –

+1

ऑर्डर द्वारा ऑर्डर में स्थिति पर निर्भरता संबंध सिद्धांत का उल्लंघन करती है, जिसमें यह माना जाता है कि परिणाम सेट में फ़ील्ड का क्रम निर्धारित नहीं है। मैं इसके बजाय "match_count द्वारा ऑर्डर" का सुझाव देता हूं। –

+1

@ जोएलफिंकेल यह कुछ भी "उल्लंघन" नहीं करता है। स्तंभों का क्रम * क्वेरी * के भीतर परिभाषित किया गया है, इसलिए encapsulation बरकरार है। यह ठीक है। मुझे समझ में नहीं आ रहा है कि क्यों कुछ लोगों को इस अविश्वसनीय रूप से मामूली समस्या पर एक गुच्छा में अपने जाँघिया मिलते हैं जो इस मामले के लिए परिणाम या किसी भी चीज़ के लिए बिल्कुल कोई फर्क नहीं पड़ता। तलना करने के लिए बड़ी मछली हैं। दरअसल, तलना करने के लिए * मछली * होती है - यह एक मछली भी नहीं है। यह कुछ भी नहीं है. – Bohemian

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