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

समय अवधि के भीतर एकाधिक समूहों के लिए अनुपलब्ध डेटा कैसे शामिल करें?

कुछ मान्यताओं (प्रश्न में अस्पष्टता) के आधार पर मेरा सुझाव है:

SELECT upper(trim(t.full_name)) AS teacher
     , m.study_month
     , r.room_code              AS room
     , count(s.room_id)         AS study_count

FROM   teachers t
CROSS  JOIN generate_series(date_trunc('month', now() - interval '12 month')  -- 12!
                          , date_trunc('month', now())
                          , interval '1 month') m(study_month)
CROSS  JOIN rooms r
LEFT   JOIN (                                                  -- parentheses!
          studies s
   JOIN   teacher_contacts tc ON tc.id = s.teacher_contact_id  -- INNER JOIN!
   ) ON tc.teacher_id = t.id
    AND s.study_dt >= m.study_month
    AND s.study_dt <  m.study_month + interval '1 month'      -- sargable!
    AND s.room_id = r.id
GROUP  BY t.id, m.study_month, r.id  -- id is PK of respective tables
ORDER  BY t.id, m.study_month, r.id;

प्रमुख बिंदु

  • CROSS JOIN . के साथ सभी वांछित संयोजनों का ग्रिड बनाएं . और फिर LEFT JOIN मौजूदा पंक्तियों के लिए। संबंधित:

  • आपके मामले में, यह कई तालिकाओं का जोड़ है, इसलिए मैं FROM में कोष्ठक का उपयोग करता हूं सूची में LEFT JOIN परिणाम . तक INNER JOIN . का कोष्ठक के भीतर। यह गलत होगा करने के लिए LEFT JOIN प्रत्येक तालिका के लिए अलग से, क्योंकि आप आंशिक मिलानों पर हिट शामिल करेंगे और संभावित रूप से गलत गणनाएं प्राप्त करेंगे।

  • मान लें कि संदर्भात्मक अखंडता और सीधे पीके कॉलम के साथ काम करते हुए, हमें rooms . को शामिल करने की आवश्यकता नहीं है और teachers दूसरी बार बाईं ओर। लेकिन हमारे पास अभी भी दो तालिकाओं (studies . का एक संयोजन है और teacher_contacts ) teacher_contacts . की भूमिका मेरे लिए अस्पष्ट है। आम तौर पर, मैं studies . के बीच संबंध की अपेक्षा करता हूं और teachers सीधे। इसे और सरल बनाया जा सकता है...

  • वांछित गणना प्राप्त करने के लिए हमें बाईं ओर एक गैर-शून्य कॉलम गिनने की आवश्यकता है। जैसे count(s.room_id)

  • बड़ी तालिकाओं के लिए इसे तेज़ रखने के लिए, सुनिश्चित करें कि आपके विधेय sargable हैं . और मिलते-जुलते इंडेक्स जोड़ें ।

  • कॉलम teachers शायद ही (विश्वसनीय रूप से) अद्वितीय है। एक अद्वितीय आईडी के साथ काम करें, अधिमानतः पीके (तेज और सरल भी)। मैं अभी भी teachers का उपयोग कर रहा हूं आउटपुट के लिए आपके वांछित परिणाम से मेल खाने के लिए। एक अद्वितीय आईडी शामिल करना बुद्धिमानी हो सकती है, क्योंकि नाम डुप्लीकेट हो सकते हैं।

  • आप चाहते हैं:

    तो date_trunc('month', now() - interval '12 month' . से शुरू करें (13 नहीं)। यह पहले से ही शुरुआत को गोल कर रहा है और वही करता है जो आप चाहते हैं - आपकी मूल क्वेरी की तुलना में अधिक सटीक।

चूंकि आपने वास्तविक तालिका परिभाषाओं और डेटा वितरण के आधार पर धीमे प्रदर्शन का उल्लेख किया है, इसलिए संभवत:पहले एकत्र करना और बाद में शामिल होना अधिक तेज़ है , जैसे इस संबंधित उत्तर में:

SELECT upper(trim(t.full_name)) AS teacher
     , m.mon                    AS study_month
     , r.room_code              AS room
     , COALESCE(s.ct, 0)        AS study_count

FROM   teachers t
CROSS  JOIN generate_series(date_trunc('month', now() - interval '12 month')  -- 12!
                          , date_trunc('month', now())
                          , interval '1 month') mon
CROSS  JOIN rooms r
LEFT   JOIN (                                                  -- parentheses!
   SELECT tc.teacher_id, date_trunc('month', s.study_dt) AS mon, s.room_id, count(*) AS ct
   FROM   studies s
   JOIN   teacher_contacts tc ON s.teacher_contact_id = tc.id
   WHERE  s.study_dt >= date_trunc('month', now() - interval '12 month')  -- sargable
   GROUP  BY 1, 2, 3
   ) s ON s.teacher_id = t.id
      AND s.mon = m.mon
      AND s.room_id = r.id
ORDER  BY 1, 2, 3;

आपकी समापन टिप्पणी के बारे में:

संभावना है कि आप कर सकते हैं crosstab() . के दो-पैरामीटर फ़ॉर्म का इस्तेमाल करें अपने वांछित परिणाम को सीधे और उत्कृष्ट प्रदर्शन के साथ उत्पन्न करने के लिए और उपरोक्त क्वेरी को शुरू करने की आवश्यकता नहीं है। विचार करें:



  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. Azure Postgres से कनेक्ट होने पर सर्वर अनपेक्षित रूप से कनेक्शन बंद कर देता है

  3. Django परीक्षण जुड़नार लोड करने में असमर्थ, IntegrityError

  4. Postgres में वर्तमान स्थानीय समय प्राप्त करने का सबसे साफ तरीका क्या है?

  5. तिथियों की एक श्रृंखला के लिए निकटतम रिकॉर्ड