आप DISTINCT ON
. के साथ प्रति समूह सबसे लंबे नाम वाले यात्री को आसानी से प्राप्त कर सकते हैं ।
लेकिन मुझे आपकी मूल क्वेरी के साथ इसे (या किसी अन्य सरल तरीके से) संयोजित करने का कोई तरीका नहीं दिखता SELECT
. मैं दो अलग-अलग उपश्रेणियों में शामिल होने का सुझाव देता हूं:
SELECT *
FROM ( -- your original query
SELECT orig
, count(*) AS flight_cnt
, count(distinct passenger) AS pass_cnt
, percentile_cont(0.5) WITHIN GROUP (ORDER BY bags) AS bag_cnt_med
FROM table1
GROUP BY orig
) org_query
JOIN ( -- my addition
SELECT DISTINCT ON (orig) orig, passenger AS pass_max_len_name
FROM table1
ORDER BY orig, length(passenger) DESC NULLS LAST
) pas USING (orig);
USING
जॉइन क्लॉज में आसानी से केवल orig
. के एक इंस्टेंस को आउटपुट करता है , तो आप बस उपयोग कर सकते हैं SELECT *
बाहरी में SELECT
।
अगर passenger
NULL हो सकता है, NULLS LAST
जोड़ना महत्वपूर्ण है :
एक ही समूह में समान अधिकतम लंबाई वाले कई यात्री नामों से, आपको एक मनमाना चयन मिलता है - जब तक आप ORDER BY
. में और भाव नहीं जोड़ते टाईब्रेकर के रूप में। ऊपर दिए गए उत्तर में विस्तृत विवरण।
प्रदर्शन?
आमतौर पर, एक स्कैन बेहतर होता है, खासकर अनुक्रमिक स्कैन के साथ।
उपरोक्त क्वेरी दो . का उपयोग करती है स्कैन (शायद इंडेक्स/इंडेक्स-ओनली स्कैन)। लेकिन दूसरा स्कैन तुलनात्मक रूप से सस्ता है जब तक कि कैश में फिट होने के लिए टेबल बहुत बड़ी न हो (ज्यादातर)। लुकास ने केवल एकल के साथ एक वैकल्पिक क्वेरी का सुझाव दिया SELECT
जोड़ना:
, (ARRAY_AGG (passenger ORDER BY LENGTH (passenger) DESC))[1] -- I'd add NULLS LAST
विचार स्मार्ट है, लेकिन पिछली बार मैंने परीक्षण किया था
, array_agg
ORDER BY
. के साथ इतना अच्छा प्रदर्शन नहीं किया। (प्रति-समूह का ऊपरी भाग ORDER BY
पर्याप्त है, और सरणी प्रबंधन भी महंगा है।)
कस्टम एग्रीगेट फ़ंक्शन के साथ वही तरीका सस्ता हो सकता है first()
जैसा कि यहां पोस्टग्रेज विकी में निर्देश दिया गया है
. या, तेज़, अभी तक, सी में लिखा गया संस्करण, PGXN पर उपलब्ध
के साथ . सरणी प्रबंधन के लिए अतिरिक्त लागत को समाप्त करता है, लेकिन हमें अभी भी प्रति-समूह ORDER BY
. की आवश्यकता है . अधिक तेज़ हो सकता है केवल कुछ समूहों के लिए। फिर आप जोड़ेंगे:
, first(passenger ORDER BY length(passenger) DESC NULLS LAST)
गॉर्डन
और लुकास
विंडो फ़ंक्शन का भी उल्लेख करें first_value()
. विंडो फ़ंक्शन बाद लागू होते हैं कुल कार्य। उसी में इसका उपयोग करने के लिए SELECT
, हमें passenger
. को एकत्रित करना होगा किसी तरह पहला - कैच 22। गॉर्डन इसे एक सबक्वेरी के साथ हल करता है - मानक पोस्टग्रेज के साथ अच्छे प्रदर्शन के लिए एक और उम्मीदवार।
first()
सबक्वेरी के बिना भी ऐसा ही करता है और सरल और थोड़ा तेज होना चाहिए। लेकिन यह अभी भी एक अलग DISTINCT ON
. से तेज़ नहीं होगा अधिकांश मामलों के लिए प्रति समूह कुछ पंक्तियों के साथ। प्रति समूह बहुत सारी पंक्तियों के लिए, एक पुनरावर्ती CTE तकनीक आमतौर पर तेज़ होती है। यदि आपके पास सभी प्रासंगिक, अद्वितीय orig
. को धारण करने वाली एक अलग तालिका है, तो और भी तेज़ तकनीकें हैं मूल्य। विवरण:
सबसे अच्छा समाधान विभिन्न कारकों पर निर्भर करता है। हलवा का सबूत खाने में है। प्रदर्शन को अनुकूलित करने के लिए आपको अपने सेटअप के साथ परीक्षण करना होगा। उपरोक्त क्वेरी सबसे तेज़ होनी चाहिए।