DISTINCT ON
PostgreSQL . में इसके लिए आम तौर पर सबसे सरल और तेज़ है .
(कुछ कार्यभार के प्रदर्शन अनुकूलन के लिए नीचे देखें।)
SELECT DISTINCT ON (customer)
id, customer, total
FROM purchases
ORDER BY customer, total DESC, id;
या छोटा (यदि उतना स्पष्ट नहीं है) आउटपुट कॉलम की क्रमिक संख्या के साथ:
SELECT DISTINCT ON (2)
id, customer, total
FROM purchases
ORDER BY 2, 3 DESC, 1;
अगर total
न्यूल हो सकता है (किसी भी तरह से चोट नहीं पहुंचाएगा, लेकिन आप मौजूदा इंडेक्स से मेल खाना चाहेंगे):
...
ORDER BY customer, total DESC NULLS LAST, id;
प्रमुख बिंदु
DISTINCT ON
मानक का एक PostgreSQL एक्सटेंशन है (जहां केवल DISTINCT
संपूर्ण SELECT
. पर सूची परिभाषित है)।
DISTINCT ON
. में कितने भी भाव सूचीबद्ध करें खंड, संयुक्त पंक्ति मान डुप्लिकेट को परिभाषित करता है। मैनुअल:
जाहिर है, दो पंक्तियों को अलग माना जाता है यदि वे कम से कम एक कॉलम मान में भिन्न हों। इस तुलना में शून्य मान समान माने जाते हैं।
बोल्ड जोर मेरा।
DISTINCT ON
के साथ जोड़ा जा सकता है ORDER BY
. ORDER BY
. में प्रमुख भाव DISTINCT ON
. में एक्सप्रेशन के सेट में होना चाहिए , लेकिन आप उन लोगों के बीच स्वतंत्र रूप से ऑर्डर पुनर्व्यवस्थित कर सकते हैं। उदाहरण।
आप अतिरिक्त जोड़ सकते हैं ORDER BY
. के भाव साथियों के प्रत्येक समूह से एक विशेष पंक्ति लेने के लिए। या, जैसा कि मैनुअल कहता है:
DISTINCT ON
अभिव्यक्ति (ओं) को सबसे बाईं ओर ORDER BY
. से मेल खाना चाहिए अभिव्यक्ति (ओं)। ORDER BY
क्लॉज में आम तौर पर अतिरिक्त एक्सप्रेशन होते हैं जो प्रत्येक DISTINCT ON
के भीतर पंक्तियों की वांछित प्राथमिकता निर्धारित करते हैं समूह।
मैंने id
जोड़ा संबंधों को तोड़ने के लिए अंतिम आइटम के रूप में:
"सबसे छोटी id
वाली पंक्ति चुनें उच्चतम total
sharing साझा करने वाले प्रत्येक समूह से ।"
परिणामों को इस तरह से ऑर्डर करने के लिए जो पहले प्रति समूह को निर्धारित करने वाले सॉर्ट ऑर्डर से असहमत हो, आप ऊपर की क्वेरी को किसी अन्य ORDER BY
के साथ एक बाहरी क्वेरी में नेस्ट कर सकते हैं। . उदाहरण।
अगर total
NULL हो सकता है, आप संभवतः सबसे बड़ी गैर-शून्य मान वाली पंक्ति चाहते हैं। जोड़ें NULLS LAST
जैसे दिखाया। देखें:
- कॉलम ASC के अनुसार क्रमित करें, लेकिन NULL मान पहले?
SELECT
सूची DISTINCT ON
. में भावों से विवश नहीं है या ORDER BY
किसी भी तरह से। (उपरोक्त साधारण मामले में आवश्यक नहीं):
-
आपको यह नहीं करना है
DISTINCT ON
. में किसी भी भाव को शामिल करें याORDER BY
। -
आप कर सकते हैं
SELECT
. में कोई अन्य व्यंजक शामिल करें सूची। यह बहुत अधिक जटिल प्रश्नों को सबक्वेरी और एग्रीगेट / विंडो फ़ंक्शंस के साथ बदलने के लिए महत्वपूर्ण है।
मैंने पोस्टग्रेज़ संस्करण 8.3 - 13 के साथ परीक्षण किया। लेकिन यह सुविधा कम से कम संस्करण 7.1 के बाद से है, इसलिए मूल रूप से हमेशा।
सूचकांक
उत्तम उपरोक्त क्वेरी के लिए अनुक्रमणिका एक बहु-स्तंभ अनुक्रमणिका होगी जो मिलान क्रम में और मिलान क्रम के साथ सभी तीन स्तंभों में फैली होगी:
CREATE INDEX purchases_3c_idx ON purchases (customer, total DESC, id);
अति विशिष्ट हो सकता है। लेकिन इसका उपयोग करें यदि किसी विशेष क्वेरी के लिए प्रदर्शन पढ़ना महत्वपूर्ण है। अगर आपके पास DESC NULLS LAST
है क्वेरी में, इंडेक्स में उसी का उपयोग करें ताकि सॉर्ट ऑर्डर मैच हो और इंडेक्स लागू हो।
प्रभावकारिता / प्रदर्शन अनुकूलन
प्रत्येक क्वेरी के लिए अनुरूप अनुक्रमणिका बनाने से पहले लागत और लाभ को तौलें। उपरोक्त सूचकांक की क्षमता काफी हद तक डेटा वितरण . पर निर्भर करती है ।
अनुक्रमणिका का उपयोग किया जाता है क्योंकि यह पूर्व-क्रमबद्ध डेटा वितरित करता है। Postgres 9.2 या बाद के संस्करण में क्वेरी केवल अनुक्रमणिका स्कैन . से भी लाभान्वित हो सकती है यदि सूचकांक अंतर्निहित तालिका से छोटा है। हालांकि, इंडेक्स को पूरी तरह से स्कैन करना होगा।
कुछ के लिए प्रति ग्राहक पंक्तियाँ (स्तंभ में उच्च कार्डिनैलिटी customer
), यह बहुत ही कुशल है। इससे भी अधिक यदि आपको वैसे भी सॉर्ट किए गए आउटपुट की आवश्यकता है। प्रति ग्राहक पंक्तियों की बढ़ती संख्या के साथ लाभ सिकुड़ता है।
आदर्श रूप से, आपके पास पर्याप्त work_mem
है रैम में शामिल सॉर्ट स्टेप को प्रोसेस करने के लिए और डिस्क पर स्पिल नहीं करने के लिए। लेकिन आम तौर पर work_mem
सेट करना भी उच्च प्रतिकूल प्रभाव डाल सकता है। SET LOCAL
. पर विचार करें असाधारण रूप से बड़े प्रश्नों के लिए। EXPLAIN ANALYZE
. के साथ पता लगाएं कि आपको कितना चाहिए . "डिस्क: . का उल्लेख करें " सॉर्ट चरण में और अधिक की आवश्यकता को इंगित करता है:
- लिनक्स पर PostgreSQL में कॉन्फ़िगरेशन पैरामीटर work_mem
- दिनांक और टेक्स्ट के अनुसार ORDER का उपयोग करके सरल क्वेरी को अनुकूलित करें
कईके लिए प्रति ग्राहक पंक्तियाँ (स्तंभ में कम कार्डिनैलिटी customer
), एक ढीली अनुक्रमणिका स्कैन (a.k.a. "स्किप स्कैन") (बहुत) अधिक कुशल होगा, लेकिन इसे पोस्टग्रेज 14 तक लागू नहीं किया गया है। (केवल-इंडेक्स स्कैन के लिए एक कार्यान्वयन पोस्टग्रेज 15 के लिए विकास में है। यहां और यहां देखें।)
के लिए अब, तेज़ क्वेरी तकनीक हैं इसके स्थानापन्न करने के लिए। विशेष रूप से यदि आपके पास अद्वितीय ग्राहकों को रखने वाली एक अलग तालिका है, जो कि विशिष्ट उपयोग का मामला है। लेकिन यह भी अगर आप नहीं करते हैं:
- पोस्टग्रेएसक्यूएल में मेरी टेबल पर उम्मीद से कम चुनें डिस्टिंक्ट है
- प्रति उपयोगकर्ता नवीनतम पंक्ति पुनर्प्राप्त करने के लिए क्वेरी द्वारा समूह को अनुकूलित करें
- समूहवार अधिकतम क्वेरी अनुकूलित करें
- प्रति पंक्ति अंतिम N संबंधित पंक्तियों को क्वेरी करें
बेंचमार्क
अलग उत्तर देखें।