Ricorsivo “ON DUPLICATE KEY UPDATE”
-
28-09-2019 - |
Domanda
Ho una tabella del database con una chiave univoca su una colonna di data in modo che non ci può mai essere più di una riga per data. Se si inserisce una nuova riga per una giornata che già esiste nel database, mi piacerebbe che per spingere tutte le successive, date consecutive indietro di un giorno fino a raggiungere un giorno ‘libero’.
Ecco quello che ho pensato:
INSERT INTO
`activity`
(`name`,`date`)
VALUES
('date 7','2009-07-31')
ON DUPLICATE KEY
UPDATE `date` = DATE_ADD(`date`, INTERVAL '1' DAY)
Il mio pensiero è che l'ON DUPLICATE KEY UPDATE si bolla il tavolo e continuare ad aggiungere un giorno per ogni data, fino a raggiungere un giorno che non esiste.
per esempio, se i miei tabella è contenuto come questo:.
date 1, 2009-07-30
date 2, 2009-07-31
date 3, 2009-08-01
date 4, 2009-08-02
date 5, 2009-08-04 <- notice this date is two days past the previous one
... e vado a inserire ‘data 7 'su 2009-07-31, mi piacerebbe che per fare questo:
date 1, 2009-07-30
date 7, 2009-07-31 <- newly inserted row
date 2, 2009-08-01 <- this and subsequent rows are all incremented
by one day until it hits a non-consecutive day
date 3, 2009-08-02
date 4, 2009-08-03
date 5, 2009-08-04 <- notice this date hasn't changed
Ma aggiornata chiave duplicata non funziona così, aggiorna solo la riga scontro, e se quella riga si scontra poi con una riga diversa, è balle fuori con un errore di chiave duplicata.
C'è un modo intelligente per ottenere questo effetto in SQL solo?
Soluzione
Domanda per il primo appuntamento gratuito o dopo la data di destinazione. Si tratta di un self-join sinistra per trovare le date con nessun successore nella tabella.
SELECT DATE_ADD(Min(a.`date`), INTERVAL '1' DAY) AS `free_date`
FROM `activity` a
LEFT JOIN `activity` z
ON z.`date` = DATE_ADD(a.`date`, INTERVAL '1' DAY)
WHERE z.`date` IS NULL
AND a.`date` >= '2009-07-31'
Esegui un aggiornamento per incrementare ogni data nell'intervallo compreso tra la data di destinazione e la prima data libera.
Ora c'è spazio per il vostro inserto desiderato.
Altri suggerimenti
seleziona la data di massima prima di fare l'aggiornamento, quindi aggiungere un giorno al massimo
qualcosa di simile:
ON DUPLICATE KEY
UPDATE `date` = DATE_ADD(select max('date') from 'activity', INTERVAL '1' DAY)