PostgreSQL
 sql >> डेटाबेस >  >> RDS >> PostgreSQL

एक ही क्वेरी में एकाधिक array_agg () कॉल

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
  • पोस्टग्रेएसक्यूएल में लेटरल और सबक्वेरी में क्या अंतर है?

कोई भी क्वेरी सभी . को बरकरार रखती है परिणाम में कर्मचारी।



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. मैं Postgres 8.2 में संदर्भात्मक अखंडता को कैसे अक्षम करूं?

  2. PostgreSQL में उच्च उपलब्धता का प्रबंधन - भाग III:Patroni

  3. PostgreSQL में मॉड () कैसे काम करता है

  4. विंडो फ़ंक्शंस या सामान्य तालिका अभिव्यक्तियाँ:पिछली पंक्तियों को सीमा के भीतर गिनें

  5. PostgreSQL में सभी उपयोगकर्ताओं को कैसे सूचीबद्ध करें