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

PostgreSQL - किसी अन्य तालिका से चयन के आधार पर पंक्तियाँ सम्मिलित करें, और उस तालिका में नई सम्मिलित पंक्तियों के साथ FK को अद्यतन करें

समस्या को हल करने के कई तरीके हैं।

<मजबूत>1. अस्थायी रूप से एक कॉलम जोड़ें

जैसा कि अन्य ने उल्लेख किया है, सीधा-आगे तरीका अस्थायी रूप से एक कॉलम जोड़ना है reminder_id dateset . तक . इसे मूल IDs with से भरें reminder . से मेज़। इसका उपयोग reminder में शामिल होने के लिए करें dateset . के साथ मेज़। अस्थायी कॉलम ड्रॉप करें।

<मजबूत>2. जब प्रारंभ अद्वितीय हो

यदि start . के मान कॉलम अद्वितीय है reminder . में शामिल होकर इसे अतिरिक्त कॉलम के बिना करना संभव है dateset के साथ तालिका start पर तालिका कॉलम।

INSERT INTO dateset (start)
SELECT start FROM reminder;

WITH
CTE_Joined
AS
(
    SELECT
        reminder.id AS reminder_id
        ,reminder.dateset_id AS old_dateset_id
        ,dateset.id AS new_dateset_id
    FROM
        reminder
        INNER JOIN dateset ON dateset.start = reminder.start
)
UPDATE CTE_Joined
SET old_dateset_id = new_dateset_id
;

<मजबूत>3. जब प्रारंभ अद्वितीय न हो

इस मामले में भी अस्थायी कॉलम के बिना ऐसा करना संभव है। मुख्य विचार निम्नलिखित है। आइए इस उदाहरण पर एक नजर डालते हैं:

हमारे पास reminder . में दो पंक्तियाँ हैं उसी के साथ start मान और आईडी 3 और 7:

reminder
id    start         dateset_id
3     2015-01-01    NULL
7     2015-01-01    NULL

हम उन्हें dateset . में डालने के बाद , नई आईडी उत्पन्न होंगी, उदाहरण के लिए, 1 और 2:

dateset
id    start
1     2015-01-01
2     2015-01-01

इससे कोई फर्क नहीं पड़ता कि हम इन दो पंक्तियों को कैसे जोड़ते हैं। अंतिम परिणाम हो सकता है

reminder
id    start         dateset_id
3     2015-01-01    1
7     2015-01-01    2

या

reminder
id    start         dateset_id
3     2015-01-01    2
7     2015-01-01    1

ये दोनों वेरिएंट सही हैं। जो हमें निम्नलिखित समाधान में लाता है।

बस पहले सभी पंक्तियां डालें।

INSERT INTO dateset (start)
SELECT start FROM reminder;

start on पर दो तालिकाओं का मिलान/जुड़ें कॉलम यह जानते हुए कि यह अद्वितीय नहीं है। ROW_NUMBER . जोड़कर "इसे अद्वितीय बनाएं" और दो कॉलम से जुड़ना। क्वेरी को छोटा करना संभव है, लेकिन मैंने प्रत्येक चरण को स्पष्ट रूप से लिखा है:

WITH
CTE_reminder_rn
AS
(
    SELECT
        id
        ,start
        ,dateset_id
        ,ROW_NUMBER() OVER (PARTITION BY start ORDER BY id) AS rn
    FROM reminder
)
,CTE_dateset_rn
AS
(
    SELECT
        id
        ,start
        ,ROW_NUMBER() OVER (PARTITION BY start ORDER BY id) AS rn
    FROM dateset
)
,CTE_Joined
AS
(
    SELECT
        CTE_reminder_rn.id AS reminder_id
        ,CTE_reminder_rn.dateset_id AS old_dateset_id
        ,CTE_dateset_rn.id AS new_dateset_id
    FROM
        CTE_reminder_rn
        INNER JOIN CTE_dateset_rn ON 
            CTE_dateset_rn.start = CTE_reminder_rn.start AND
            CTE_dateset_rn.rn = CTE_reminder_rn.rn
)
UPDATE CTE_Joined
SET old_dateset_id = new_dateset_id
;

मुझे आशा है कि यह कोड से स्पष्ट है कि यह क्या करता है, खासकर जब आप इसकी तुलना ROW_NUMBER के बिना सरल संस्करण से करते हैं . जाहिर है, जटिल समाधान काम करेगा भले ही start अद्वितीय है, लेकिन यह एक साधारण समाधान जितना कुशल नहीं है।

यह समाधान मानता है कि dateset इस प्रक्रिया से पहले खाली है।



  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. यह कैसे संभव है कि SQL क्वेरी और ActiveRecord.find_by_sql अलग-अलग परिणाम लौटाएं?

  3. हेरोकू - ActiveRecord ::StatementInvalid (पीजी ::त्रुटि:त्रुटि:अनुरोधित कॉलम मौजूद नहीं है

  4. सभी स्कीमा में PostgreSQL एक्सटेंशन स्थापित करना

  5. PostGIS त्रुटि:एक सर्वश्रेष्ठ उम्मीदवार समारोह का चयन नहीं कर सका