Elimina le righe sql in cui gli ID non hanno una corrispondenza da un'altra tabella


161

Sto cercando di eliminare le voci orfane in una tabella mysql.

Ho 2 tavoli come questo:

Tabella files:

| id | ....
------------
| 1  | ....
| 2  | ....
| 7  | ....
| 9  | ....

tabella blob:

| fileid | ....
------------
| 1  | ....
| 2  | ....
| 3  | ....
| 4  | ....
| 4  | ....
| 4  | ....
| 9  | ....

Le colonne fileide idpossono essere utilizzate per unire le tabelle.

Voglio eliminare tutte le righe nella tabella blobdove fileidnon è possibile trovare nella tabella files.id.

Quindi, usando l'esempio sopra che eliminerebbe le righe: 3 & 4 nella blobtabella.


1
Passa alla seconda risposta se stai usando nulls.
Pacerier,

Risposte:


328

Utilizzando LEFT JOIN / IS NULL:

DELETE b FROM BLOB b 
  LEFT JOIN FILES f ON f.id = b.fileid 
      WHERE f.id IS NULL

Utilizzando NOT EXISTS:

DELETE FROM BLOB 
 WHERE NOT EXISTS(SELECT NULL
                    FROM FILES f
                   WHERE f.id = fileid)

Utilizzando NOT IN:

DELETE FROM BLOB
 WHERE fileid NOT IN (SELECT f.id 
                        FROM FILES f)

avvertimento

Quando possibile, esegui DELETE all'interno di una transazione (supponendo supportato - IE: Not on MyISAM) in modo da poter utilizzare il rollback per ripristinare le modifiche in caso di problemi.


12
qual è, in generale, il più veloce di quanto sopra?
Hampus Brynolf,

2
Per qualche motivo, la cancellazione tramite LEFT JOIN non ha funzionato su MS SQL Server Mgmt Studio (non so perché, si è semplicemente lamentato di LEFT JOIN). Qualcuno sa perché? Ha funzionato usando NOT EXISTS però :)
Anna,

5
Cordiali saluti, ecco una discussione utile della relativa efficienza di questi tre metodi: explainextended.com/2009/09/18/...
moustachio

2
@Pacerier - "wrong" è un po 'forte. Per assicurarsi che la gente capisce, le risposte fanno lavoro se fileidè non annullabile . Inoltre, la terza soluzione ( NOT IN) richiede che f.idnon sia nullable. Presumibilmente questa è una chiave primaria, quindi sarebbe.
ToolmakerSteve

2
Per le persone che tentano questo con SQLite: vedi questa risposta
bunkerdive,

26
DELETE FROM blob 
WHERE fileid NOT IN 
       (SELECT id 
        FROM files 
        WHERE id is NOT NULL/*This line is unlikely to be needed 
                               but using NOT IN...*/
      )

Che cosa è "/ * È improbabile che questa riga sia necessaria ma che si suppone significhi usare NOT IN ... * /" ?
Pacerier,

1
@Pacerier: NOT IN (NULL)restituisce un set di risultati vuoto, pertanto è necessario escludere i NULL. Ma idprobabilmente una colonna non sarà nulla da rendere quindi "improbabile che sia necessaria"
Martin Smith,

Wow buona cattura. Quindi la risposta di omgponies è sbagliata! not in(null)è abbastanza logico, perché non funziona? Qual è la logica alla base di ciò?
Pacerier,


1
@bunkerdive Quindi utilizzare nomi di oggetti in tre parti che includono il nome del database.
Martin Smith,

18
DELETE FROM blob
WHERE NOT EXISTS (
    SELECT *
    FROM files
    WHERE id=blob.id
)

1
Penso che ci sia un files.ide blob.fileid. Immagino che la tua query provocherà un errore.
1919

-9
delete from table1 t1 
    WHERE not exists (select id from table2 where related_field_in_t2=t1.id) 
    AND not exists (select id from table3 where related_field_in_t3=t1.id) 
    AND not exists (select id from table4 where related_field_t4=t1.id) 
    AND not exists (select id from table5 where related_field_t5=t1.id);

3
Ho effettuato il downvoting perché: 1. Questo non tenta di rispondere alla domanda nel contesto che è stato pubblicato. 2. Non c'è spiegazione (e le risposte di solo codice hanno un valore basso su StackOverflow). 3. è NOT EXISTSstato già pubblicato 9 anni fa. 4. Non hai promosso la migliore pratica di utilizzare costantemente le maiuscole per le parole chiave MySQL. In altre parole, qui non c'è nulla che valga la pena di tenere: ecco perché ho anche votato per eliminare questo post.
Mickmackusa,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.