如何从 MySQL 中的选择中删除?

Posted

技术标签:

【中文标题】如何从 MySQL 中的选择中删除?【英文标题】:How to delete from select in MySQL? 【发布时间】:2011-06-01 13:23:42 【问题描述】:

此代码不适用于 mysql 5.0,如何重写以使其工作

DELETE FROM posts where id=(SELECT id FROM posts GROUP BY id  HAVING ( COUNT(id) > 1 ))

我想删除没有唯一 ID 的列。我会补充一点,大多数时候它只有一个 id(我尝试了 in 语法,但它也不起作用)。

【问题讨论】:

【参考方案1】:

SELECT(子)查询返回结果集合。所以你需要在WHERE 子句中使用IN,而不是=

此外,如this answer 所示,您不能从同一查询中的子查询修改同一表。但是,您可以在单独的查询中使用SELECT 然后DELETE,或者嵌套另一个子查询并为内部子查询结果设置别名(虽然看起来很hacky):

DELETE FROM posts WHERE id IN (
    SELECT * FROM (
        SELECT id FROM posts GROUP BY id HAVING ( COUNT(id) > 1 )
    ) AS p
)

或者使用连接as suggested by Mchl。

【讨论】:

我有一个包含 150 个重复键的表。我执行了上面的查询,它说“144行受影响”,但那里仍然有重复的键。所以我再次执行查询,它说 5 行受影响,再次:1 行受影响。然后所有重复的键都消失了。这是为什么呢? 发生这种情况,因为您只从每组重复项中删除 1 个条目:SELECT id FROM posts GROUP BY id HAVING ( COUNT(id) > 1 ) #1248 - 每个派生表都必须有自己的别名 @thang:这就是我说给内部子查询起别名的原因。 请您解释一下“As p”是做什么的?【参考方案2】:
DELETE 
  p1
  FROM posts AS p1 
CROSS JOIN (
  SELECT ID FROM posts GROUP BY id HAVING COUNT(id) > 1
) AS p2
USING (id)

【讨论】:

这似乎可行,但我对语法感到困惑,无法在其他地方找到任何资源来解释它。 CROSS JOIN 显然执行了笛卡尔连接,所以看起来这可能会做不必要的工作,或者表现不佳?谁能解释一下? 只有在没有USING 子句的情况下才会进行笛卡尔积。对于USING,产品仅限于id 列中具有相同值的对,因此实际上非常有限。 你能用内部连接做同样的事情吗? IE。 DELETE p1 FROM posts AS p1 INNER JOIN ( SELECT ID FROM posts GROUP BY id HAVING COUNT(id) > 1 ) AS p2 ON p2.ID=p1.ID @Andrew:是的。从功能上讲,这些连接完全相同。【参考方案3】:

你可以使用内连接:

DELETE 
    ps 
FROM 
    posts ps INNER JOIN 
         (SELECT 
           distinct id 
         FROM 
             posts 
         GROUP BY id  
      HAVING COUNT(id) > 1 ) dubids on dubids.id = ps.id  

【讨论】:

【参考方案4】:

如果您想删除所有重复项,但要删除每组重复项中的一个,这是一种解决方案:

DELETE posts
FROM posts
LEFT JOIN (
    SELECT id
    FROM posts
    GROUP BY id
    HAVING COUNT(id) = 1

    UNION

    SELECT id
    FROM posts
    GROUP BY id
    HAVING COUNT(id) != 1
) AS duplicate USING (id)
WHERE duplicate.id IS NULL;

【讨论】:

以上是关于如何从 MySQL 中的选择中删除?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 MySQL 中的 JSON 结果中删除括号

如何从 MySQL 中的表中删除列

如何从mysql中的表中删除重复的行

如何从mysql5中的父表中删除数据?

如何从 MySQL 中的多个表中删除?

如何从 Wordpress (MySQL) 中的多个帖子中删除宽度和高度属性