Eliminar todas las filas de una tabla basada en otra tabla

81

¡Parece que no puedo recordar esta consulta!

Quiero eliminar todas las filas en la tabla1 cuyas ID son las mismas que en la Tabla2.

Entonces:

DELETE table1 t1
 WHERE t1.ID = t2.ID

Sé que puedo hacer un ID DÓNDE EN (SELECCIONAR ID DE LA tabla2) pero quiero hacer esta consulta usando un JOIN si es posible.

mrblah
fuente
¿Por qué quieres unirte?
tster
¿Qué planeas hacer con esta pregunta: stackoverflow.com/questions/1590709/…
OMG Ponies
Porque las uniones suelen ser más rápidas.
HLGEM
@tster Quizás sea una tabla temporal de identificadores que deben eliminarse
Stephen Mesa
1
@HLGEM ¿Está diciendo que el optimizador de consultas no es lo suficientemente inteligente como para hacer una simple "eliminación de X donde XY IN (seleccione Foo de la barra)" tan rápido como hacer una combinación? Confiaría en el optimizador sobre el instinto.
tster

Respuestas:

87
DELETE Table1
FROM Table1
INNER JOIN Table2 ON Table1.ID = Table2.ID
Stephen Mesa
fuente
88
DELETE t1 
FROM Table1 t1
JOIN Table2 t2 ON t1.ID = t2.ID;

Siempre uso el alias en la declaración de eliminación, ya que evita el accidente.

DELETE Table1 

causado al no resaltar toda la consulta antes de ejecutarla.

HLGEM
fuente
5
Votar a favor principalmente por el comentario de "usar siempre el alias" Gran idea.
rosscova
35

No hay una solución en ANSI SQL para usar combinaciones en eliminaciones, AFAIK.

DELETE FROM Table1
WHERE Table1.id IN (SELECT Table2.id FROM Table2)

Posteriormente editar

Otra solución (a veces funciona más rápido):

DELETE FROM Table1
WHERE EXISTS( SELECT 1 FROM Table2 Where Table1.id = Table2.id)
Cătălin Pitiș
fuente
Su pregunta dice al final que quiere usar una combinación en lugar de la cláusula IN.
Stephen Mesa
21

La implementación de PostgreSQL sería:

DELETE FROM t1
USING t2
WHERE t1.id = t2.id;
Vesanto
fuente
4

Prueba esto:

DELETE Table1
FROM Table1 t1, Table2 t2
WHERE t1.ID = t2.ID;

o

DELETE Table1
FROM Table1 t1 INNER JOIN Table2 t2 ON t1.ID = t2.ID;
Yannick Motton
fuente
3

Creo que podrías obtener un poco más de rendimiento si intentas esto

DELETE FROM Table1
WHERE EXISTS (
  SELECT 1
  FROM Table2
  WHERE Table1.ID = Table2.ID
)
bogertron
fuente
3

Esto eliminará todas las filas Table1que coincidan con los criterios:

DELETE Table1 
FROM Table2 
WHERE Table1.JoinColumn = Table2.JoinColumn And Table1.SomeStuff = 'SomeStuff'
Más
fuente
2

Encontré este enlace útil

Copiado de allí

A menudo, uno desea eliminar algunos registros de una tabla según los criterios de otra tabla. ¿Cómo se elimina de una de esas tablas sin eliminar los registros en ambas tablas?

DELETE DeletingFromTable
     FROM DeletingFromTable INNER JOIN CriteriaTable
     ON DeletingFromTable.field_id = CriteriaTable.id
     WHERE CriteriaTable.criteria = "value";

La clave es que especifique el nombre de la tabla que se eliminará como SELECT. Entonces, JOIN y WHERE hacen la selección y la limitación, mientras que DELETE hace la eliminación. Sin embargo, no está limitado a una sola mesa. Si tiene una relación de varios a varios (por ejemplo, revistas y suscriptores, unidos por una suscripción) y está eliminando un suscriptor, también debe eliminar todos los registros potenciales del modelo de unión.

 DELETE subscribers, subscriptions
     FROM subscribers INNER JOIN subscriptions 
       ON subscribers.id = subscriptions.subscriber_id
     INNER JOIN magazines 
       ON subscriptions.magazine_id = magazines.id
     WHERE subscribers.name='Wes';

La eliminación de registros con una combinación también se puede hacer con LEFT JOIN y WHERE para ver si la tabla unida era NULL, de modo que pueda eliminar registros en una tabla que no tiene una coincidencia (como en preparación para agregar una relación. ) Ejemplo de publicación por venir.

Ankur Gupta
fuente
2

Dado que el OP no solicita una base de datos específica, es mejor utilizar una declaración compatible con el estándar. Solo MERGEestá en el estándar SQL para eliminar (o actualizar) filas mientras se une algo en la tabla de destino.

merge table1 t1
    using (
        select t2.ID
            from table2 t2
    ) as d
    on t1.ID = d.ID
    when matched then delete;

MERGEtiene una semántica más estricta, protegiendo de algunos casos de error que pueden pasar desapercibidos con DELETE ... FROM. Hace cumplir la 'unicidad' de la coincidencia: si muchas filas en la fuente (la declaración dentro using) coinciden con la misma fila en el destino, la fusión debe cancelarse y el motor SQL debe generar un error.

Frédéric
fuente
esto es más limpio que la construcción delete-join
asakura89
0

Haciendo referencia a MSDN T-SQL DELETE (Ejemplo D):

DELETE FROM Table1
FROM Tabel1 t1
   INNER JOIN Table2 t2 on t1.ID = t2.ID
Austin Salonen
fuente
0

Para eliminar registros de tabla basados ​​en otra tabla

     Delete From Table1 a,Table2 b where a.id=b.id

    Or

      DELETE FROM Table1
    WHERE Table1.id IN (SELECT Table2.id FROM Table2)

  Or

        DELETE Table1
     FROM Table1 t1 INNER JOIN Table2 t2 ON t1.ID = t2.ID;
kavitha Reddy
fuente
0

Esto es viejo, lo sé, pero solo un indicador para cualquiera que use este culo como referencia. Acabo de probar esto y si está utilizando Oracle, JOIN no funciona en las declaraciones DELETE. Recibes el siguiente mensaje:

ORA-00933: El comando SQL no finalizó correctamente.

KS1
fuente
Consulte esta respuesta a otra pregunta para ver un ejemplo de cómo escribir una eliminación con combinación en Oracle.
Frédéric
0

Si bien el OP no quiere usar una declaración 'in', en respuesta a Ankur Gupta, esta fue la forma más fácil que encontré para eliminar los registros en una tabla que no existían en otra tabla, en una relación de uno a muchos :

DELETE
FROM Table1 as t1
WHERE ID_Number NOT IN
(SELECT ID_Number FROM Table2 as t2)

Funcionó de maravilla en Access 2016, para mí.

Robar
fuente
0

A menudo hago cosas como el siguiente ejemplo inventado. (Este ejemplo es de Informix SE que se ejecuta en Linux).

El objetivo de este ejemplo es eliminar todos los registros de transacciones de exención / reducción de bienes raíces, porque la aplicación de reducción tiene un error, según la información de la tabla real_estate.

En este caso, last_update != nullsignifica que la cuenta no está cerrada, y res_exempt != 'p'significa que las cuentas no son propiedad personal (equipo / mobiliario comercial).

delete from trans 
where   yr = '16'
and     tran_date = '01/22/2016'
and     acct_type = 'r'
and     tran_type = 'a'
and     bill_no in
(select acct_no from real_estate where last_update is not null
 and res_exempt != 'p');

Me gusta este método porque los criterios de filtrado, al menos para mí, son más fáciles de leer al crear la consulta y de entender dentro de muchos meses cuando los miro y me pregunto qué estaba pensando.

pulpo
fuente
0
delete
    table1
from 
    t2
where
    table1.ID=t2.ID

Funciona en mssql

Ken Kin
fuente