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

n समूहीकृत श्रेणियां प्राप्त करें और दूसरों को एक में जोड़ें

विशिष्ट कठिनाई यहां:SELECT . में एक या अधिक समग्र फ़ंक्शन वाली क्वेरीज़ सूची और कोई GROUP BY क्लॉज बिल्कुल एक पंक्ति उत्पन्न करता है, भले ही कोई पंक्ति न मिले अंतर्निहित तालिका में।

WHERE . में आप कुछ नहीं कर सकते उस पंक्ति को दबाने के लिए खंड। तथ्य के बाद . आपको ऐसी पंक्ति को बाहर करना होगा , यानी HAVING . में खंड, या किसी बाहरी प्रश्न में।

प्रति दस्तावेज़:

<ब्लॉकक्वॉट>

अगर किसी क्वेरी में कुल फ़ंक्शन कॉल हैं, लेकिन कोई GROUP BY नहीं है खंड, समूहीकरण अभी भी होता है:परिणाम एक एकल समूह पंक्ति है (या शायद बिल्कुल भी नहीं है, यदि एकल पंक्ति को HAVING द्वारा समाप्त कर दिया जाता है ) वही सच है अगर इसमें HAVING . है क्लॉज, बिना किसी एग्रीगेट फंक्शन कॉल या GROUP BY . के भी खंड।

यह ध्यान दिया जाना चाहिए कि GROUP BY . जोड़ना केवल एक निरंतर अभिव्यक्ति के साथ खंड (जो अन्यथा पूरी तरह से व्यर्थ है!) भी काम करता है। नीचे उदाहरण देखें। लेकिन मैं उस तरकीब का उपयोग नहीं करना चाहूंगा, भले ही वह छोटी, सस्ती और सरल हो, क्योंकि यह शायद ही स्पष्ट है कि यह क्या करती है।

निम्न क्वेरी के लिए केवल एकल तालिका स्कैन की आवश्यकता है और गिनती के आधार पर क्रमित शीर्ष 7 श्रेणियां लौटाता है। अगर (और केवल तभी ) और भी श्रेणियां हैं, बाकी को 'अन्य' में संक्षेपित किया गया है:

WITH cte AS (
   SELECT categoryid, count(*) AS data
        , row_number() OVER (ORDER BY count(*) DESC, categoryid) AS rn
   FROM   contents
   GROUP  BY 1
   )
(  -- parentheses required again
SELECT categoryid, COALESCE(ca.name, 'Unknown') AS label, data
FROM   cte
LEFT   JOIN category ca ON ca.id = cte.categoryid
WHERE  rn <= 7
ORDER  BY rn
)
UNION ALL
SELECT NULL, 'Others', sum(data)
FROM   cte
WHERE  rn > 7         -- only take the rest
HAVING count(*) > 0;  -- only if there actually is a rest
-- or: HAVING  sum(data) > 0
  • यदि कई श्रेणियों की 7वीं/8वीं रैंक पर समान गणना हो सकती है, तो आपको संबंध तोड़ने की आवश्यकता है। मेरे उदाहरण में, छोटे categoryid . वाली श्रेणियां ऐसी दौड़ जीतें।

  • कोष्ठक में LIMIT . शामिल करना आवश्यक है या ORDER BY एक UNION . के एक व्यक्तिगत पैर के लिए खंड क्वेरी।

  • आपको केवल तालिका category में शामिल होने की आवश्यकता है शीर्ष 7 श्रेणियों के लिए। और आम तौर पर पहले एकत्र करना और बाद में इस परिदृश्य में शामिल होना सस्ता होता है। इसलिए cte नाम के CTE (कॉमन टेबल एक्सप्रेशन) में बेस क्वेरी में शामिल न हों , केवल पहले SELECT . में शामिल हों UNION . का प्रश्न, यह सस्ता है।

  • सुनिश्चित नहीं हैं कि आपको COALESCE की आवश्यकता क्यों है . अगर आपके पास contents.categoryid . से कोई विदेशी कुंजी है करने के लिए category.id और दोनों contents.categoryid और category.name परिभाषित हैं NOT NULL (जैसे वे शायद होना चाहिए), तो आपको इसकी आवश्यकता नहीं है।

विषम GROUP BY true

यह भी काम करेगा:

...

UNION ALL
SELECT NULL , 'Others', sum(data)
FROM   cte
WHERE  rn > 7
GROUP BY true; 

और मुझे थोड़ी तेज क्वेरी प्लान भी मिलते हैं। लेकिन यह एक अजीब हैक है...

एसक्यूएल फिडल सभी का प्रदर्शन।

UNION ALL . के लिए अधिक स्पष्टीकरण के साथ संबंधित उत्तर / LIMIT तकनीक:

  • कुछ प्रश्नों के योग परिणाम और फिर SQL में शीर्ष 5 खोजें


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. मेरे पोस्टग्रेस्क्ल डेटाबेस को केस असंवेदनशील संयोजन का उपयोग कैसे करें?

  2. PostgreSQL में एन्क्रिप्टेड पासवर्ड के साथ उपयोगकर्ता बनाना

  3. PostgreSQL DESCRIBE टेबल समतुल्य

  4. हाइबरनेट का उपयोग करके फ्लाई पर PostgreSQL डेटाबेस बनाएं, भले ही डीबी मौजूद न हो

  5. परफेक्ट के साथ पोस्टग्रेएसक्यूएल ट्रेसिंग