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

एसक्यूएल ग्रुपिंग इंटरसेक्टिंग/ओवरलैपिंग रो

यह मानते हुए कि सभी जोड़े उनके प्रतिबिंबित संयोजन में भी मौजूद हैं (4,5) और (5,4) . लेकिन निम्नलिखित समाधान मिरर किए गए डुप्ली के बिना भी काम करते हैं।

साधारण मामला

सभी कनेक्शनों को एकल आरोही क्रम . में पंक्तिबद्ध किया जा सकता है और जटिलताएं जैसे मैंने fiddle में जोड़ी हैं संभव नहीं हैं, हम आरसीटीई में डुप्लीकेट के बिना इस समाधान का उपयोग कर सकते हैं:

मैं न्यूनतम a_sno . प्राप्त करके प्रारंभ करता हूं प्रति समूह, न्यूनतम संबद्ध b_sno . के साथ :

SELECT row_number() OVER (ORDER BY a_sno) AS grp
     , a_sno, min(b_sno) AS b_sno
FROM   data d
WHERE  a_sno < b_sno
AND    NOT EXISTS (
   SELECT 1 FROM data
   WHERE  b_sno = d.a_sno
   AND    a_sno < b_sno
   )
GROUP  BY a_sno;

इसके लिए केवल एक क्वेरी स्तर की आवश्यकता है क्योंकि एक विंडो फ़ंक्शन को समग्र पर बनाया जा सकता है:

परिणाम:

grp  a_sno  b_sno
1    4      5
2    9      10
3    11     15

मैं शाखाओं और डुप्लिकेट (गुणा) पंक्तियों से बचता हूं - संभावित रूप से बहुत लंबी श्रृंखलाओं के साथ अधिक महंगा। मैं ORDER BY b_sno LIMIT 1 . का उपयोग करता हूं इस मक्खी को पुनरावर्ती CTE में बनाने के लिए एक सहसंबद्ध उपश्रेणी में।

प्रदर्शन की कुंजी एक मेल खाने वाली अनुक्रमणिका है, जो पहले से ही पीके बाधा PRIMARY KEY (a_sno,b_sno) द्वारा प्रदान की गई है। :दूसरे तरीके से नहीं <स्ट्राइक>(b_sno, a_sno) :

WITH RECURSIVE t AS (
   SELECT row_number() OVER (ORDER BY d.a_sno) AS grp
        , a_sno, min(b_sno) AS b_sno  -- the smallest one
   FROM   data d
   WHERE  a_sno < b_sno
   AND    NOT EXISTS (
      SELECT 1 FROM data
      WHERE  b_sno = d.a_sno
      AND    a_sno < b_sno
      )
   GROUP  BY a_sno
   )

, cte AS (
   SELECT grp, b_sno AS sno FROM t

   UNION ALL
   SELECT c.grp
       , (SELECT b_sno  -- correlated subquery
          FROM   data
          WHERE  a_sno = c.sno
          AND    a_sno < b_sno
          ORDER  BY b_sno
          LIMIT  1)
   FROM   cte  c
   WHERE  c.sno IS NOT NULL
   )
SELECT * FROM cte
WHERE  sno IS NOT NULL   -- eliminate row with NULL
UNION  ALL               -- no duplicates
SELECT grp, a_sno FROM t
ORDER  BY grp, sno;

कम सरल मामला

सभी नोड्स को जड़ से एक या अधिक शाखाओं के साथ आरोही क्रम में पहुँचा जा सकता है (सबसे छोटा sno )।

इस बार, सभी प्राप्त करें ग्रेटर sno और डी-डुप्लिकेट नोड्स जिन्हें UNION . के साथ कई बार देखा जा सकता है अंत में:

WITH RECURSIVE t AS (
   SELECT rank() OVER (ORDER BY d.a_sno) AS grp
        , a_sno, b_sno  -- get all rows for smallest a_sno
   FROM   data d
   WHERE  a_sno < b_sno
   AND    NOT EXISTS (
      SELECT 1 FROM data
      WHERE  b_sno = d.a_sno
      AND    a_sno < b_sno
      )
   )   
, cte AS (
   SELECT grp, b_sno AS sno FROM t

   UNION ALL
   SELECT c.grp, d.b_sno
   FROM   cte  c
   JOIN   data d ON d.a_sno = c.sno
                AND d.a_sno < d.b_sno  -- join to all connected rows
   )
SELECT grp, sno FROM cte
UNION                     -- eliminate duplicates
SELECT grp, a_sno FROM t  -- add first rows
ORDER  BY grp, sno;

पहले समाधान के विपरीत, हमें यहां NULL के साथ अंतिम पंक्ति नहीं मिलती है (सहसंबद्ध सबक्वेरी के कारण)।

दोनों को बहुत अच्छा प्रदर्शन करना चाहिए - खासकर लंबी जंजीरों/कई शाखाओं के साथ। वांछित परिणाम:

SQL Fiddle (कठिनाई प्रदर्शित करने के लिए अतिरिक्त पंक्तियों के साथ)।

अप्रत्यक्ष ग्राफ़

यदि स्थानीय मिनीमा हैं जो आरोही ट्रैवर्सल के साथ रूट से नहीं पहुंचा जा सकता है, तो उपरोक्त समाधान काम नहीं करेंगे। Farhęg's Solution पर विचार करें इस मामले में।



  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. पोस्टग्रे एसक्यूएल फ़िल्टरिंग स्थिति को अनदेखा करता है यदि मान शून्य है

  3. क्या समाप्ति समय निर्धारित करने का कोई तरीका है, जिसके बाद PostgreSQL में डेटा प्रविष्टि स्वचालित रूप से हटा दी जाती है?

  4. django नाक परीक्षण में hstore एक्सटेंशन स्थापित करना

  5. रिकॉर्ड के कॉलम के माध्यम से लूप