Estoy tratando de hacer una consulta como esta:
DELETE FROM term_hierarchy AS th
WHERE th.parent = 1015 AND th.tid IN (
SELECT DISTINCT(th1.tid)
FROM term_hierarchy AS th1
INNER JOIN term_hierarchy AS th2 ON (th1.tid = th2.tid AND th2.parent != 1015)
WHERE th1.parent = 1015
);
Como probablemente pueda ver, quiero eliminar la relación principal con 1015 si el mismo tid tiene otros padres. Sin embargo, eso me produce un error de sintaxis:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AS th
WHERE th.parent = 1015 AND th.tid IN (
SELECT DISTINCT(th1.tid)
FROM ter' at line 1
Verifiqué la documentación y ejecuté la subconsulta por sí misma, y todo parece verificar. ¿Alguien puede averiguar qué está mal aquí?
Actualización : como se responde a continuación, MySQL no permite que la tabla de la que está eliminando se use en una subconsulta para la condición.
DELETE t FROM table t ...
Respuestas:
No puede especificar la tabla de destino para eliminar.
Una solución
create table term_hierarchy_backup (tid int(10)); <- check data type insert into term_hierarchy_backup SELECT DISTINCT(th1.tid) FROM term_hierarchy AS th1 INNER JOIN term_hierarchy AS th2 ON (th1.tid = th2.tid AND th2.parent != 1015) WHERE th1.parent = 1015; DELETE FROM term_hierarchy AS th WHERE th.parent = 1015 AND th.tid IN (select tid from term_hierarchy_backup);
fuente
Para otros que encuentran esta pregunta buscando eliminar mientras usan una subconsulta, les dejo este ejemplo para burlar a MySQL (incluso si algunas personas parecen pensar que no se puede hacer):
DELETE e.* FROM tableE e WHERE id IN (SELECT id FROM tableE WHERE arg = 1 AND foo = 'bar');
te dará un error:
ERROR 1093 (HY000): You can't specify target table 'e' for update in FROM clause
Sin embargo esta consulta:
DELETE e.* FROM tableE e WHERE id IN (SELECT id FROM (SELECT id FROM tableE WHERE arg = 1 AND foo = 'bar') x);
funcionará bien:
Envuelva su subconsulta en una subconsulta adicional (aquí llamada x) y MySQL hará felizmente lo que le pida.
fuente
e
) en un DELETE y en su sub-SELECT. Nosotros podemos , sin embargo, utilizar un sub-sub-SELECT para crear una tabla temporal (x
), y el uso que para el sub-SELECT.El alias debe incluirse después de la
DELETE
palabra clave:DELETE th FROM term_hierarchy AS th WHERE th.parent = 1015 AND th.tid IN ( SELECT DISTINCT(th1.tid) FROM term_hierarchy AS th1 INNER JOIN term_hierarchy AS th2 ON (th1.tid = th2.tid AND th2.parent != 1015) WHERE th1.parent = 1015 );
fuente
Debe hacer referencia al alias nuevamente en la declaración de eliminación, como:
DELETE th FROM term_hierarchy AS th ....
Como se describe aquí en los documentos de MySQL.
fuente
delete from your_table as t1 where t1.id in(select t2.id from your_table t2);
¿qué obtuviste?Currently, you cannot delete from a table and select from the same table in a subquery.
dev.mysql.com/doc/refman/5.5/en/delete.htmlMe acerqué a esto de una manera ligeramente diferente y funcionó para mí;
Necesitaba eliminar
secure_links
de mi tabla que hacía referencia a laconditions
tabla donde ya no quedaban filas de condición. Básicamente, un guión de limpieza. Esto me dio el error: no puede especificar la tabla de destino para eliminar.Entonces, buscando inspiración aquí, se me ocurrió la siguiente consulta y funciona bien. Esto se debe a que crea una tabla temporal
sl1
que se usa como referencia para DELETE.DELETE FROM `secure_links` WHERE `secure_links`.`link_id` IN ( SELECT `sl1`.`link_id` FROM ( SELECT `sl2`.`link_id` FROM `secure_links` AS `sl2` LEFT JOIN `conditions` ON `conditions`.`job` = `sl2`.`job` WHERE `sl2`.`action` = 'something' AND `conditions`.`ref` IS NULL ) AS `sl1` )
Funciona para mi.
fuente
¿No es la cláusula "in" en la eliminación ... donde, extremadamente ineficaz, si va a haber una gran cantidad de valores devueltos desde la subconsulta? No estoy seguro de por qué no se uniría simplemente interno (o derecho) contra la tabla original de la subconsulta en el ID para eliminar, en lugar de nosotros el "in (subconsulta)".
DELETE T FROM Target AS T RIGHT JOIN (full subquery already listed for the in() clause in answers above) ` AS TT ON (TT.ID = T.ID)
Y tal vez se responda en "MySQL no lo permite", sin embargo, funciona bien para mí SIEMPRE que me asegure de aclarar completamente qué eliminar (ELIMINAR T DE Target AS T). Eliminar con Join en MySQL aclara el problema DELETE / JOIN.
fuente
Si desea hacer esto con 2 consultas, siempre puede hacer algo similar a esto:
1) agarre los identificadores de la mesa con:
SELECT group_concat(id) as csv_result FROM your_table WHERE whatever = 'test' ...
Luego copie el resultado con el mouse / teclado o el lenguaje de programación a XXX a continuación:
2) DELETE FROM your_table WHERE id IN ( XXX )
Tal vez podrías hacer esto en una consulta, pero esto es lo que prefiero.
fuente
@CodeReaper, @BennyHill: Funciona como se esperaba.
Sin embargo, me pregunto cuál es la complejidad del tiempo para tener millones de filas en la tabla. Aparentemente, tardó
5ms
en ejecutarse para tener 5k registros en una tabla indexada correctamente.Mi consulta:
SET status = '1' WHERE id IN ( SELECT id FROM ( SELECT c2.id FROM clusters as c2 WHERE c2.assign_to_user_id IS NOT NULL AND c2.id NOT IN ( SELECT c1.id FROM clusters AS c1 LEFT JOIN cluster_flags as cf on c1.last_flag_id = cf.id LEFT JOIN flag_types as ft on ft.id = cf.flag_type_id WHERE ft.slug = 'closed' ) ) x)``` Or is there something we can improve on my query above?
fuente
puede usar el alias de esta manera en la declaración de eliminación
DELETE th.* FROM term_hierarchy th INNER JOIN term_hierarchy th2 ON (th1.tid = th2.tid AND th2.parent != 1015) WHERE th.parent = 1015;
fuente