DISTINCT
अक्सर उन प्रश्नों को ठीक करने के लिए लागू किया जाता है जो अंदर से सड़े हुए होते हैं, और यह अक्सर धीमा और / या गलत होता है। शुरू करने के लिए पंक्तियों को गुणा न करें, फिर आपको अंत में अवांछित डुप्लिकेट को सॉर्ट करने की आवश्यकता नहीं है।
एक साथ कई एन-टेबल ("कई हैं") में शामिल होना परिणाम सेट में पंक्तियों को गुणा करता है। यह एक CROSS JOIN
जैसा है या कार्टेशियन उत्पाद प्रॉक्सी द्वारा :
- दो SQL लेफ्ट जॉइन गलत परिणाम देते हैं
इस गलती से बचने के कई तरीके हैं।
पहले एकत्र करें, बाद में शामिल हों
तकनीकी रूप से, क्वेरी तब तक काम करती है जब तक आप एक . से जुड़ते हैं आपके एकत्रित होने से पहले एक बार में एकाधिक पंक्तियों वाली तालिका:
SELECT e.id, e.name, e.age, e.streets, arrag_agg(wd.day) AS days
FROM (
SELECT e.id, e.name, e.age, array_agg(ad.street) AS streets
FROM employees e
JOIN address ad ON ad.employeeid = e.id
GROUP BY e.id -- id enough if it is defined PK
) e
JOIN workingdays wd ON wd.employeeid = e.id
GROUP BY e.id, e.name, e.age;
प्राथमिक कुंजी id
. को शामिल करना भी सबसे अच्छा है और GROUP BY
यह, क्योंकि name
और age
जरूरी नहीं कि अद्वितीय हों। आप गलती से दो कर्मचारियों का विलय कर सकते हैं।
लेकिन आप पहले . एक सबक्वेरी में एकत्र कर सकते हैं आप शामिल हों, यह तब तक बेहतर है जब तक आपके पास चुनिंदा WHERE
. न हो employees
. पर शर्तें :
SELECT e.id, e.name, e.age, ad.streets, arrag_agg(wd.day) AS days
FROM employees e
JOIN (
SELECT employeeid, array_agg(ad.street) AS streets
FROM address
GROUP BY 1
) ad ON ad.employeeid = e.id
JOIN workingdays wd ON e.id = wd.employeeid
GROUP BY e.id, e.name, e.age, ad.streets;
या दोनों को एकत्रित करें:
SELECT name, age, ad.streets, wd.days
FROM employees e
JOIN (
SELECT employeeid, array_agg(ad.street) AS streets
FROM address
GROUP BY 1
) ad ON ad.employeeid = e.id
JOIN (
SELECT employeeid, arrag_agg(wd.day) AS days
FROM workingdays
GROUP BY 1
) wd ON wd.employeeid = e.id;
आखिरी वाला आमतौर पर तेज होता है यदि आप सभी या अधिक को पुनः प्राप्त करते हैं बेस टेबल में पंक्तियों की संख्या।
ध्यान दें कि JOIN
. का उपयोग करके और नहीं LEFT JOIN
उन कर्मचारियों को परिणाम से निकालता है जिनका कोई पता नहीं है या कोई कार्यदिवस नहीं। इसका इरादा हो भी सकता है और नहीं भी। LEFT JOIN
पर स्विच करें सभी . को बनाए रखने के लिए परिणाम में कर्मचारी।
सहसंबंधित सबक्वेरी / लेटरल जॉइन
छोटे चयन . के लिए , मैं इसके बजाय सहसंबद्ध उपश्रेणियों पर विचार करूंगा:
SELECT name, age
, (SELECT array_agg(street) FROM address WHERE employeeid = e.id) AS streets
, (SELECT arrag_agg(day) FROM workingdays WHERE employeeid = e.id) AS days
FROM employees e
WHERE e.namer = 'peter'; -- very selective
या, 9.3 या बाद के संस्करण के साथ, आप LATERAL
. का उपयोग कर सकते हैं उसके लिए शामिल हों:
SELECT e.name, e.age, a.streets, w.days
FROM employees e
LEFT JOIN LATERAL (
SELECT array_agg(street) AS streets
FROM address
WHERE employeeid = e.id
GROUP BY 1
) a ON true
LEFT JOIN LATERAL (
SELECT array_agg(day) AS days
FROM workingdays
WHERE employeeid = e.id
GROUP BY 1
) w ON true
WHERE e.name = 'peter'; -- very selective
- पोस्टग्रेएसक्यूएल में लेटरल और सबक्वेरी में क्या अंतर है?
कोई भी क्वेरी सभी . को बरकरार रखती है परिणाम में कर्मचारी।