以子查询为条件从中删除MySQL
我正在尝试这样的查询:以子查询为条件从中删除MySQL,mysql,sql,subquery,sql-delete,in-subquery,Mysql,Sql,Subquery,Sql Delete,In Subquery,我正在尝试这样的查询: 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 =
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
);
正如您可能知道的,如果同一tid有其他父项,我想删除与1015的父项关系。但是,这会产生一个语法错误:
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
我已经检查了文档,并自行运行了子查询,所有这些似乎都检查出来了。有人能找出这里出了什么问题吗
更新:如下所述,MySQL不允许在条件的子查询中使用要从中删除的表。您需要在delete语句中再次引用别名,如:
DELETE th FROM term_hierarchy AS th
....
不能指定要删除的目标表 变通办法
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);
别名应包含在DELETE关键字之后:
对于那些在使用子查询时发现这个问题想要删除的人,我给你们留下这个例子,让你们比MySQL更精彩,即使有些人似乎认为这是不可能的:
DELETE e.*
FROM tableE e
WHERE id IN (SELECT id
FROM tableE
WHERE arg = 1 AND foo = 'bar');
将给您一个错误:
ERROR 1093 (HY000): You can't specify target table 'e' for update in FROM clause
但是,此查询:
DELETE e.*
FROM tableE e
WHERE id IN (SELECT id
FROM (SELECT id
FROM tableE
WHERE arg = 1 AND foo = 'bar') x);
会很好用的:
Query OK, 1 row affected (3.91 sec)
将您的子查询包装在一个名为x的附加子查询中,MySQL将很乐意满足您的要求。我以一种稍微不同的方式处理这个问题,它对我很有效 我需要从引用条件表的表中删除secure_链接,其中不再剩下任何条件行。基本上是一个内务脚本。这给了我一个错误-您不能指定要删除的目标表 所以在这里寻找灵感,我提出了下面的问题,效果很好。 这是因为它创建了一个临时表sl1,用作删除的引用
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`
)
对我有用。不是删除中的in子句。。。如果子查询返回了大量的值,效率会非常低吗?不知道为什么您不只是从要删除的ID上的子查询中对原始表进行内部或右键联接,而不是在子查询中对我们进行联接
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)
也许MySQL不允许这样做,但它对我来说很好,前提是我确保完全澄清从目标中删除什么作为t。澄清了删除/加入问题。如果你想通过两个查询来实现这一点,你总是可以做类似的事情: 1从表中抓取ID,包括:
SELECT group_concat(id) as csv_result FROM your_table WHERE whatever = 'test' ...
然后用鼠标/键盘或编程语言将结果复制到下面的XXX:
2) DELETE FROM your_table WHERE id IN ( XXX )
也许您可以在一个查询中完成此操作,但这正是我喜欢的。@CodeReaper,@BennyHill:
它按预期工作
然而,我想知道表中有数百万行的时间复杂性是什么?显然,在一个索引正确的表上有5k条记录需要大约5ms才能执行
我的问题是:
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?
您可以通过这种方式在delete语句中使用别名
DELETE th.*
FROM term_hierarchy th
INNER JOIN term_hierarchy th2 ON (th1.tid = th2.tid AND th2.parent != 1015)
WHERE th.parent = 1015;
不是关于alias的,请检查OPagain@ajreal-是的,请注意错误从别名定义开始,MySQL文档明确指出您需要在DELETE语句以及FROM子句中使用别名。不过,感谢您的否决票。只需从您的_表中删除t1,其中t1.id插入从您的_表t2中选择t2.id;你得到了什么?文件清楚地说明;当前,不能从表中删除,也不能从子查询中的同一表中选择。您不必修复别名,只需在delete中不指定要选择的目标表……这是真正的问题,我们都是对的——请参阅下面他对我答案的评论。别名语法和逻辑都有问题:是的,似乎通过子查询删除在MySQL中目前是不可能的——感谢您的关注:从term_hierarchy中删除和最后一行中的th不是有同样的问题吗?我得到了一个与OP相同的语法错误。您应该将索引添加到术语_hierarchy_backup.tid中。我能够验证这一点,2019年在MariaDB 10.3.14或MySQL Community Server 5.7.27上都不可能,但我花了一些时间让它工作。重要提示:1第一个表必须使用e作为别名,2结尾的x不是占位符,它是由子查询SELECT id FROM table(其中arg=1,foo=bar)生成的临时表的别名。为什么这样做?这对我来说变化很大,但更重要的是,它不应该起作用。它确实有效,但不应该。难以置信。这确实有效!但您不必将表别名为e。。。您可以使用任何您想要的别名。@jakabadambalazs我的推理是,以SELECT id开头的子查询将完成并返回一个id列表,从而释放您要从中删除的表的锁。@jakabadambalazs:我们不能在delete及其子SELECT中使用相同的表e。但是,我们可以使用子选择来创建临时表x,并将其用于子选择。这是一个很好的答案。正确的别名将大大有助于解决与原始帖子类似的问题。和我一样。注意:下面的答案很好,只需在从表t中删除t后添加表别名…与上面@CodeReaper中的相同。。。 很好的电话;
DELETE th.*
FROM term_hierarchy th
INNER JOIN term_hierarchy th2 ON (th1.tid = th2.tid AND th2.parent != 1015)
WHERE th.parent = 1015;