2009-11-23 39 views
24

Esto es probablemente muy fácil, pero es lunes por la mañana. Tengo dos tablas:SQL Eliminar filas basadas en otra tabla

Cuadro 1:

Field  | Type    | Null | Key | Default | Extra 
id   | int(32) unsigned | NO | PRI | NULL | auto_increment 
group  | int(32)   | NO |  | 0  |     

Tabla2:

Field  | Type    | Null | Key | Default | Extra 
group  | int(32)   | NO |  | 0  | 

Ignorar a otros campos ... Me gustaría declaración que eliminar todas las filas de la Tabla 1 un solo SQL DELETE para el cual existe un Table2.group igual a Table1.group. Por lo tanto, si una fila de la Tabla 1 tiene un grupo = 69, esa fila debe eliminarse si y solo si existe una fila en la Tabla 2 con el grupo = 69.

Gracias por cualquier ayuda.

Respuesta

35

Creo que esto es lo que quiere:

DELETE FROM `table1` 
WHERE `group` in (SELECT DISTINCT `group` FROM `table2`) 
+0

muchos gracias. –

+0

¡Me salvó el día! Gracias @ ¡Jay! – Lefteris

+0

Eso es simple y muy efectivo. Funciona en el servidor SQL (pero sin las comillas simples). –

7

Algo como esto

delete from table1 where group in (select group from table2) 
+0

I' d select distinct en la subconsulta –

+0

¿No está utilizando solo trabajo distinto para eliminar duplicados de la subconsulta? Yo lo dejaría. –

1

De la parte superior de mi cabeza:

delete from Table1 where id in (select id from table1 inner join table2 on Table1.group = Table2.group) 

lo hice un poco diferente a Otros carteles: creo que si hay una gran cantidad de filas en Table2 esto podría ser mejor. ¿Alguien puede por favor decirme eso?

+0

Todavía vuelve a una lista IN, lo cual es problemático. Considere el ejemplo @AmoBrinkman o el BT26; estos no requieren que el motor haga una gran variedad. Por ejemplo, puede cambiar "where id in" a "where exists" y probablemente debería funcionar de manera idéntica, pero mucho más rápido y "en absoluto" para grandes volúmenes. – troy

8

La buena solución es simplemente escribiendo el SQL como usted dice usted mismo ya:

DELETE FROM Table1 
WHERE 
    EXISTS(SELECT 1 FROM Table2 WHERE Table2.Group = Table1.Group) 

Saludos, Arno Brinkman

+1

Me gusta acerca de esta solución que contiene una cláusula WHERE.Esto significa que seguirá funcionando si desea eliminar solo aquellas líneas que coincidan en varias columnas en las dos tablas. – malamut

+0

@ArnoBrinkman agregaría 'LIMIT 1' a:' EXISTS (SELECCIONE 1 FROM Table2 WHERE Table2.Group = Table1.Group LIMIT 1) '¿Ayuda? –

16

Creo que de esta manera es más rápido:

DELETE FROM t1 USING table1 t1 INNER JOIN table2 t2 ON (t1.group = t2.group); 
+0

En SQL Server esto parece no funcionar: SSMS me lanza esto para la consulta anterior: ** Sintaxis incorrecta cerca de 'USING'. ** – Oliver

+4

En el caso de SQL Server, la sintaxis es: ELIMINAR DESDE t1 ** FROM t1 ** INNER JOIN T2 ON t1.ID = t2.ID Esto elimina todas las filas de t1 que existen en la tabla t2 en función de la identificación, pero se pueden agregar más condiciones a la cláusula de unión interna como normalmente con el operador AND. Fíjate en el segundo ¿De ?! No está allí por error y eso es lo que hace que USAR funcione en SQL Server. – kuklei

+0

Si está eliminando tablas realmente grandes de InnoDB, puede considerar aumentar su 'innodb_buffer_pool_size'. Esta primera falla después de 30 minutos de ejecución para mí, así que aumenté a 512 MB y logré eliminar unos 13 millones de registros adicionales. Las tablas a las que me uniré fueron de 44 millones y 23 millones de registros, respectivamente, a su orden en la consulta. –

Cuestiones relacionadas