2010-12-26 9 views
38

में किसी अन्य तालिका में पंक्तियों की गिनती का चयन करें, मुझे यह नहीं पता कि इसे कैसे वाक्यांशित किया जाए, इसलिए कृपया मुझे शीर्षक के साथ भी मदद करें। :)पोस्टग्रेस SELECT कथन

मेरे पास दो टेबल हैं। आइए उन्हें A और B पर कॉल करें। B तालिका में a_id विदेशी कुंजी है जो A.id पर इंगित करती है। अब मैं SELECT कथन लिखना चाहता हूं जो परिणाम 0 सेट में प्रत्येक पंक्ति के लिए A पंक्ति प्रति B रिकॉर्ड की एक अतिरिक्त कॉलम के साथ सभी A रिकॉर्ड्स प्राप्त करता है।

मैं अभी पोस्टग्रेस्क्ल 9 का उपयोग कर रहा हूं, लेकिन मुझे लगता है कि यह एक सामान्य SQL प्रश्न होगा?

संपादित करें:

अंत मैं ट्रिगर-कैश समाधान है, जहां A.b_count हर बार एक समारोह के माध्यम से अद्यतन किया जाता है B परिवर्तन के लिए चला गया है।

SELECT a.id, a.other_column, ..., 
(SELECT COUNT(*) FROM b where b.a_id = a.id) AS b_count 
FROM a; 
+0

यह एक प्रदर्शन के कारणों के लिए शामिल हों उपयोग करने के लिए बेहतर हो सकता है। –

उत्तर

65
SELECT A.*, (SELECT COUNT(*) FROM B WHERE B.a_id = A.id) AS TOT FROM A 
+4

क्या इस प्रकार के नेस्टेड चयन के बारे में चिंता करने के लिए एक प्रदर्शन जुर्माना है? – hayavuk

+0

हां, वहाँ है। नेस्टेड चयन को प्रत्येक पंक्ति के लिए निष्पादित किया जाएगा जिसे तालिका ए –

+0

एचएम से पुनर्प्राप्त किया गया है, इसलिए मुझे लगता है कि यह एक तालिका में कॉलम बनाने के लिए और अधिक कुशल होगा, और एक तालिका के साथ मान को अपडेट करें जब बी टेबल संशोधित है? – hayavuk

0

अपने ही सवाल का जवाब करने के लिए। ट्रिगर समाधान शायद सबसे अच्छा एक ज्यादातर पढ़ने के लिए डेटाबेस में है, लेकिन रिकार्ड के लिए यहाँ एक दृष्टिकोण है कि एक सबक्वेरी की तुलना में बेहतर प्रदर्शन करेंगे में शामिल होने के लिए:

SELECT a.id, a.xxx, count(*) 
FROM a JOIN b ON (b.a_id = a.id) 
GROUP BY a.id, a.xxx 

आप Django ORM उपयोग कर रहे हैं तो आप बस लिख सकते हैं:

res = A.objects.annotate(Count('b')) 
print res[0].b__count # holds the result count 
9

सबक्वेरी समाधान ऊपर दिए गए अक्षम है:

+0

एचएम, ऐसा करने के कई तरीके हैं।:) मैंने ट्रिगर्स को इम्प्लांट किया है, और चूंकि यह एप्लिकेशन का अधिकतर पढ़ा गया हिस्सा है (यह डैशबोर्ड पर प्रति निर्देशिका रिकॉर्ड के साथ निर्देशिका-प्रकार आइटम की एक सूची है), मुझे लगता है कि यह सबसे सुरक्षित शर्त है। – hayavuk

+0

क्या होगा यदि आपके पास दर्जनों कॉलम हैं? –

+2

पोस्टग्रेएसक्यूएल 9.1 के बाद से "ग्रुप बाय प्राथमिक_कीकॉलम" करने के लिए पर्याप्त है, पहले के संस्करणों में आपको ग्रुप बाय में सभी चुने गए कॉलम का नाम देना होगा। – intgr

17

मुझे लगता है कि @intgr द्वारा किसी अन्य उत्तर में टिप्पणी इतनी मूल्यवान है कि मैं इसे वैकल्पिक उत्तर के रूप में आगे बढ़ा रहा हूं क्योंकि यह विधि आपको गणना की गई कॉलम को कुशलतापूर्वक फ़िल्टर करने की अनुमति देती है।

SELECT 
    a.* 
    COUNT(b.id) AS b_count 

FROM a 
INNER JOIN b on b.a_id = a.id 
WHERE a.id > 50 AND b.ID < 100 -- example of filtering joined tabled 

GROUP BY a.id 
HAVING COUNT(b.id) > 10 -- example of filtering calculated column 
ORDER BY a.id 
3

स्वीकार किए गए उत्तर मेरे परीक्षणों के आधार पर अक्षम (धीमी) है। टेबल बी की प्रत्येक पंक्ति के लिए निष्पादन तालिका बी का सबक्वायरी। मैं समूहबद्ध करने और शामिल होने के आधार पर निम्नलिखित दृष्टिकोण का उपयोग कर रहा हूं। यह बहुत तेजी से काम करता है:

SELECT A.id, QTY.quantity FROM A 
LEFT JOIN 
    (SELECT COUNT(B.a_id) AS quantity, B.a_id FROM B GROUP BY B.a_id) AS QTY 
ON A.id = QTY.a_id 

एक और प्रकार:

SELECT A.id, COUNT(B.a_id) AS quantity FROM A 
LEFT JOIN B ON B.a_id = A.id 
GROUP BY A.id 
संबंधित मुद्दे