sql >> Database >  >> RDS >> PostgreSQL

PostgreSQL - voeg rijen in op basis van een selectie uit een andere tabel en werk een FK in die tabel bij met de nieuw ingevoegde rijen

Er zijn verschillende manieren om het probleem op te lossen.

1. tijdelijk een kolom toevoegen

Zoals anderen al zeiden, is de eenvoudige manier om tijdelijk een kolom toe te voegen reminder_id naar de dateset . Vul het in met originele IDs van reminder tafel. Gebruik het om deel te nemen aan reminder met de dateset tafel. Laat de tijdelijke kolom vallen.

2. wanneer start uniek is

Als waarden van de start kolom is uniek het is mogelijk om het zonder extra kolom te doen door lid te worden van reminder tabel met de dateset tabel op de start kolom.

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. wanneer start niet uniek is

Het is zelfs in dit geval mogelijk om het zonder tijdelijke kolom te doen. De hoofdgedachte is de volgende. Laten we eens naar dit voorbeeld kijken:

We hebben twee rijen in reminder met dezelfde start waarde en ID's 3 en 7:

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

Nadat we ze hebben ingevoegd in de dateset , worden er nieuwe ID's gegenereerd, bijvoorbeeld 1 en 2:

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

Het maakt niet echt uit hoe we deze twee rijen met elkaar verbinden. Het eindresultaat zou kunnen zijn

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

of

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

Beide varianten zijn correct. Dat brengt ons bij de volgende oplossing.

Voeg gewoon eerst alle rijen in.

INSERT INTO dateset (start)
SELECT start FROM reminder;

Match/doe mee aan twee tafels op start kolom wetende dat het niet uniek is. "Maak het" uniek door ROW_NUMBER . toe te voegen en verbonden door twee kolommen. Het is mogelijk om de zoekopdracht korter te maken, maar ik heb elke stap expliciet beschreven:

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
;

Ik hoop dat uit de code duidelijk is wat het doet, vooral als je het vergelijkt met de eenvoudigere versie zonder ROW_NUMBER . Het is duidelijk dat de complexe oplossing werkt, zelfs als start is uniek, maar niet zo efficiënt als een simpele oplossing.

Deze oplossing gaat ervan uit dat dateset is leeg vóór dit proces.



  1. Foutcode:1052. Kolom 'ATTRIBUTE' in veldlijst is dubbelzinnig

  2. Converteer XML naar Table SQL Server

  3. php-array van mysql

  4. Voorwaardelijke INSERT INTO-instructie in postgres