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

पोस्टग्रेज:सामान्य ईमेल पते द्वारा खातों को एक ही पहचान में एकत्रित करें

demo1:db<>fiddle , demo2:db<>fiddle

WITH combined AS (
    SELECT
        a.email as a_email,
        b.email as b_email,
        array_remove(ARRAY[a.id, b.id], NULL) as ids
    FROM 
        a
    FULL OUTER JOIN b ON (a.email = b.email)
), clustered AS (
    SELECT DISTINCT
        ids
    FROM (
        SELECT DISTINCT ON (unnest_ids) 
            *, 
            unnest(ids) as unnest_ids 
        FROM combined
        ORDER BY unnest_ids, array_length(ids, 1) DESC
    ) s
)
SELECT DISTINCT
    new_id, 
    unnest(array_cat) as email
FROM (
    SELECT
        array_cat(
            array_agg(a_email) FILTER (WHERE a_email IS NOT NULL), 
            array_agg(b_email) FILTER (WHERE b_email IS NOT NULL)
        ), 
        row_number() OVER () as new_id
    FROM combined co
    JOIN clustered cl
    ON co.ids <@ cl.ids
    GROUP BY cl.ids
) s

चरण दर चरण स्पष्टीकरण:

स्पष्टीकरण के लिए मैं यह डेटासेट लूंगा। यह आपकी तुलना में थोड़ा अधिक जटिल है। यह मेरे कदमों को बेहतर तरीके से समझा सकता है। आपके छोटे सेट में कुछ समस्याएं नहीं होती हैं। वर्णों के बारे में ईमेल पतों के लिए चर के रूप में सोचें।

तालिका A:

| id | email |
|----|-------|
|  1 |     a |
|  1 |     b |
|  2 |     c |
|  5 |     e |

टेबल बी

| id | email |
|----|-------|
|  3 |     a |
|  3 |     d |
|  4 |     e |
|  4 |     f |
|  3 |     b |

सीटीई combined :

स्पर्श बिंदु प्राप्त करने के लिए एक ही ईमेल पते पर दोनों तालिकाओं में शामिल हों। एक ही आईडी की आईडी को एक सरणी में जोड़ा जाएगा:

|   a_email |   b_email | ids |
|-----------|-----------|-----|
|    (null) | [email protected] |   3 |
| [email protected] | [email protected] | 1,3 |
| [email protected] |    (null) |   1 |
| [email protected] |    (null) |   2 |
|    (null) | [email protected] |   4 |

सीटीई clustered (नामों के लिए खेद है...):

लक्ष्य सभी तत्वों को केवल एक सरणी में प्राप्त करना है। combined . में आप देख सकते हैं, उदाहरण के लिए वर्तमान में 4 . तत्व के साथ अधिक सरणियाँ हैं :{5,4} और {4}

पहले पंक्तियों को उनके ids . की लंबाई के अनुसार क्रमित करना सरणियाँ क्योंकि DISTINCT बाद में सबसे लंबी सरणी लेनी चाहिए (क्योंकि स्पर्श बिंदु को पकड़े हुए {5,4} {4} . के बजाय )।

फिर unnest ids फ़िल्टरिंग के लिए आधार प्राप्त करने के लिए सरणी। यह इस पर समाप्त होता है:

| a_email | b_email | ids | unnest_ids |
|---------|---------|-----|------------|
|       b |       b | 1,3 |          1 |
|       a |       a | 1,3 |          1 |
|       c |  (null) |   2 |          2 |
|       b |       b | 1,3 |          3 |
|       a |       a | 1,3 |          3 |
|  (null) |       d |   3 |          3 |
|       e |       e | 5,4 |          4 |
|  (null) |       f |   4 |          4 |
|       e |       e | 5,4 |          5 |

DISTINCT ON . के साथ फ़िल्टर करने के बाद

| a_email | b_email | ids | unnest_ids |
|---------|---------|-----|------------|
|       b |       b | 1,3 |          1 |
|       c |  (null) |   2 |          2 |
|       b |       b | 1,3 |          3 |
|       e |       e | 5,4 |          4 |
|       e |       e | 5,4 |          5 |

हम केवल ids . में रुचि रखते हैं उत्पन्न अद्वितीय आईडी क्लस्टर के साथ कॉलम। इसलिए हमें उन सभी की केवल एक बार आवश्यकता है। यह आखिरी का काम है DISTINCT . तो CTE clustered परिणाम

| ids |
|-----|
|   2 |
| 1,3 |
| 5,4 |

अब हम जानते हैं कि कौन सी आईडी संयुक्त हैं और उन्हें अपना डेटा साझा करना चाहिए। अब हम क्लस्टर किए गए ids . में शामिल हो गए हैं मूल तालिकाओं के विपरीत। चूंकि हमने इसे CTE combined . में किया है हम इस हिस्से का पुन:उपयोग कर सकते हैं (यही कारण है कि इसे एक सीटीई में आउटसोर्स किया जाता है:हमें अब इस चरण में दोनों तालिकाओं के एक और जुड़ाव की आवश्यकता नहीं है)। जॉइन ऑपरेटर <@ कहते हैं:अगर combined . के "टच पॉइंट" सरणी में शामिल हों clustered . के आईडी क्लस्टर का एक उपसमूह है . यह इसमें उत्पन्न होता है:

| a_email | b_email | ids | ids |
|---------|---------|-----|-----|
|       c |  (null) |   2 |   2 |
|       a |       a | 1,3 | 1,3 |
|       b |       b | 1,3 | 1,3 |
|  (null) |       d |   3 | 1,3 |
|       e |       e | 5,4 | 5,4 |
|  (null) |       f |   4 | 5,4 |

अब हम क्लस्टर आईडी (सबसे दाहिने कॉलम) का उपयोग करके ईमेल पतों को समूहबद्ध करने में सक्षम हैं।

array_agg एक कॉलम के मेल को एकत्रित करता है, array_cat दोनों स्तंभों के ईमेल सरणियों को एक बड़े ईमेल सरणी में संयोजित करता है।

चूंकि ऐसे कॉलम हैं जहां ईमेल NULL है हम FILTER (WHERE...) . के साथ क्लस्टर करने से पहले इन मानों को फ़िल्टर कर सकते हैं खंड।

अब तक का परिणाम:

| array_cat |
|-----------|
|         c |
| a,b,a,b,d |
|     e,e,f |

अब हम सभी ईमेल पतों को एक ही आईडी के लिए समूहित करते हैं। हमें नई यूनिक आईडी बनानी होगी। यही है विंडो फ़ंक्शन row_number के लिए है। यह केवल तालिका में एक पंक्ति गणना जोड़ता है:

| array_cat | new_id |
|-----------|--------|
|         c |      1 |
| a,b,a,b,d |      2 |
|     e,e,f |      3 |

अंतिम चरण है unnest प्रति ईमेल पता एक पंक्ति प्राप्त करने के लिए सरणी। चूंकि सरणी में अभी भी कुछ डुप्लीकेट हैं, इसलिए हम उन्हें इस चरण में DISTINCT के साथ समाप्त कर सकते हैं साथ ही:

| new_id | email |
|--------|-------|
|      1 |     c |
|      2 |     a |
|      2 |     b |
|      2 |     d |
|      3 |     e |
|      3 |     f |


  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. Node.js में PostgreSQL बहु-पंक्ति अद्यतन

  3. विदेशी कुंजी के साथ रिकॉर्ड प्रविष्टि के लिए, डालने से लौटाई गई आईडी का उपयोग करना

  4. PostgreSQL फ़ंक्शंस में भाषा sql और भाषा plpgsql के बीच अंतर

  5. Postgresql में पंक्ति मिलान होने तक चयन करें?