हाँ, ओवरलैप ऑपरेटर &&
सरणियों पर GIN अनुक्रमणिका का उपयोग कर सकता है
. किसी दिए गए व्यक्ति के साथ पंक्तियों को खोजने के लिए यह प्रश्नों के लिए बहुत उपयोगी है (1
) अभिनेताओं की एक सरणी के बीच:
SELECT * FROM eg_assoc WHERE actors && '{1}'::int[]
हालांकि , आपकी क्वेरी का तर्क दूसरी तरफ है, eg_assoc
में सरणियों में सूचीबद्ध सभी व्यक्तियों की तलाश करना . GIN इंडेक्स नहीं है यहाँ मदद करो। हमें बस PK person.id
. की btree अनुक्रमणिका चाहिए ।
उचित क्वेरी
मूल बातें:
निम्नलिखित क्वेरी मूल सरणियों को संरक्षित करती हैं बिल्कुल दिए गए अनुसार , संभावित डुप्लिकेट तत्वों और तत्वों के मूल क्रम सहित। 1-आयामी सरणियों के लिए काम करता है . अतिरिक्त आयामों को एकल आयाम में जोड़ दिया जाता है। कई आयामों को संरक्षित करना अधिक जटिल है (लेकिन पूरी तरह से संभव है):
WITH ORDINALITY
पोस्टग्रेज 9.4 या बाद के संस्करण में
SELECT aid, actors
, ARRAY(SELECT name
FROM unnest(e.actors) WITH ORDINALITY a(id, i)
JOIN eg_person p USING (id)
ORDER BY a.i) AS act_names
, benefactors
, ARRAY(SELECT name
FROM unnest(e.benefactors) WITH ORDINALITY b(id, i)
JOIN eg_person USING (id)
ORDER BY b.i) AS ben_names
FROM eg_assoc e;
LATERAL
प्रश्न
PostgreSQL के लिए 9.3+ ।
SELECT e.aid, e.actors, a.act_names, e.benefactors, b.ben_names
FROM eg_assoc e
, LATERAL (
SELECT ARRAY( SELECT name
FROM generate_subscripts(e.actors, 1) i
JOIN eg_person p ON p.id = e.actors[i]
ORDER BY i)
) a(act_names)
, LATERAL (
SELECT ARRAY( SELECT name
FROM generate_subscripts(e.benefactors, 1) i
JOIN eg_person p ON p.id = e.benefactors[i]
ORDER BY i)
) b(ben_names);
db<>fiddle यहां
कुछ प्रकारों के साथ।
पुराना sqlfiddle
उप>
सूक्ष्म विवरण:यदि कोई व्यक्ति नहीं मिलता है, तो उसे छोड़ दिया जाता है। ये दोनों क्वेरी एक खाली सरणी उत्पन्न करती हैं ('{}'
) यदि संपूर्ण सरणी के लिए कोई व्यक्ति नहीं मिलता है। अन्य क्वेरी शैलियाँ NULL
लौटा देंगी . मैंने पहेली में विविधताएं जोड़ीं।
सहसंबंधित सबक्वेरी
पोस्टग्रेज के लिए 8.4+ (जहां generate_subsrcipts()
पेश किया गया था):
SELECT aid, actors
, ARRAY(SELECT name
FROM generate_subscripts(e.actors, 1) i
JOIN eg_person p ON p.id = e.actors[i]
ORDER BY i) AS act_names
, benefactors
, ARRAY(SELECT name
FROM generate_subscripts(e.benefactors, 1) i
JOIN eg_person p ON p.id = e.benefactors[i]
ORDER BY i) AS ben_names
FROM eg_assoc e;
पोस्टग्रेज 9.3 में भी सर्वश्रेष्ठ प्रदर्शन कर सकता है।
द ARRAY
कंस्ट्रक्टर
array_agg()
. से तेज़ है . देखें:
आपकी विफल क्वेरी
@a_horse द्वारा प्रदान की गई क्वेरी लगता है काम करने के लिए, लेकिन यह अविश्वसनीय, भ्रामक, संभावित रूप से गलत और अनावश्यक रूप से महंगा है।
-
दो असंबंधित जुड़ने के कारण प्रॉक्सी क्रॉस जॉइन। एक डरपोक विरोधी पैटर्न। देखें:
DISTINCT
. के साथ सतही रूप से ठीक किया गया मेंarray_agg()
उत्पन्न डुप्लिकेट को समाप्त करने के लिए, लेकिन यह वास्तव में एक सुअर पर लिपस्टिक लगा रहा है। यह मूल में डुप्लिकेट को भी हटा देता है क्योंकि इस बिंदु पर अंतर बताना असंभव है - जो संभावित रूप से गलत है। -
व्यंजक
a_person.id = any(eg_assoc.actors)
काम करता है , लेकिन डुप्लिकेट को हटा देता है परिणाम से (इस क्वेरी में दो बार होता है), जो निर्दिष्ट किए जाने तक गलत है। -
मूल सरणी तत्वों का क्रम संरक्षित नहीं है . यह सामान्य रूप से मुश्किल है। लेकिन इस सवाल में यह बढ़ गया है, क्योंकि अभिनेता और उपकारक गुणा और फिर से अलग हो जाते हैं, जो गारंटी देता है मनमाना आदेश।
-
बाहरी
SELECT
में कोई स्तंभ उपनाम नहीं है डुप्लिकेट कॉलम नामों में परिणाम, जो कुछ क्लाइंट को विफल कर देता है (उपनाम के बिना बेला में काम नहीं कर रहा है)। -
min(actors)
औरmin(benefactors)
बेकार हैं। आम तौर पर कोई केवलGROUP BY
. में कॉलम जोड़ देगा उन्हें नकली-एकत्रित करने के बजाय। लेकिनeg_assoc.aid
वैसे भी PK कॉलम है (GROUP BY
. में पूरी तालिका को कवर करना) ), तो यह आवश्यक भी नहीं है। बसactors, benefactors
।
पूरे परिणाम को एकत्रित करना शुरू करने के लिए समय और प्रयास बर्बाद कर रहा है। एक बेहतर क्वेरी का उपयोग करें जो आधार पंक्तियों को गुणा नहीं करती है, फिर आपको उन्हें वापस एकत्रित करने की आवश्यकता नहीं है।