Ci sono diversi modi per risolvere il problema.
1. aggiungere temporaneamente una colonna
Come altri hanno detto, il modo in cui straight-forward è di aggiungere temporaneamente una colonna reminder_id
al dateset
. Compilalo con il numero IDs
originale dal tavolo reminder
. Usalo per unire reminder
con la tabella dateset
. Elimina la colonna temporanea.
2. quando l'inizio è unico
Se i valori della colonna start
è unico, è possibile farlo senza colonna in più unendo reminder
tabella con la tabella dateset
sulla colonna 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. quando inizio non riservate
E 'possibile farlo senza colonna temporanea anche in questo caso. L'idea principale è la seguente. Diamo uno sguardo a questo esempio:
abbiamo due righe in reminder
con lo stesso valore di start
e ID 3 e 7:
reminder
id start dateset_id
3 2015-01-01 NULL
7 2015-01-01 NULL
Dopo che li inseriamo nella dateset
, ci saranno nuovi ID generati , ad esempio, 1 e 2:
dateset
id start
1 2015-01-01
2 2015-01-01
Non importa in realtà come colleghiamo queste due righe. Il risultato finale potrebbe essere
reminder
id start dateset_id
3 2015-01-01 1
7 2015-01-01 2
o
reminder
id start dateset_id
3 2015-01-01 2
7 2015-01-01 1
Entrambe queste varianti sono corrette. Il che ci porta alla seguente soluzione.
È sufficiente inserire prima tutte le righe.
INSERT INTO dateset (start)
SELECT start FROM reminder;
Partita/join due tabelle su start
colonna sapendo che non è unico. "Rendilo" unico aggiungendo ROW_NUMBER
e unendo due colonne. E 'possibile rendere la query più breve, ma ho spiegato ogni passo in modo esplicito:
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
;
Spero sia chiaro dal codice quello che fa, soprattutto quando si confronta con la versione più semplice, senza ROW_NUMBER
. Ovviamente, la soluzione complessa funzionerà anche se start
è univoco, ma non è così efficiente come una soluzione semplice.
Questa soluzione presuppone che dateset
sia vuoto prima di questo processo.
Come funziona '2.'? Sembra che questa variante possa funzionare solo se le CTE possono essere considerate come viste e aggiornate.Penso che al momento questo non sia possibile nei postgres. –
@matthiaskrull, sembra che tu abbia ragione. Stavo usando la sintassi di SQL Server e non ho Postgres a portata di mano per controllare. In Postgres è necessario utilizzare la clausola 'FROM' nell'istruzione [' UPDATE'] (http://www.postgresql.org/docs/9.4/static/sql-update.html) per unire le tabelle. –