【问题标题】:Delete sql rows where IDs do not have a match from another table从另一个表中删除 ID 不匹配的 sql 行
【发布时间】:2011-03-23 23:37:36
【问题描述】:

我正在尝试删除 mysql 表中的孤立条目。

我有 2 个这样的表:

files:

| id | ....
------------
| 1  | ....
| 2  | ....
| 7  | ....
| 9  | ....

blob:

| fileid | ....
------------
| 1  | ....
| 2  | ....
| 3  | ....
| 4  | ....
| 4  | ....
| 4  | ....
| 9  | ....

fileidid 列可用于将表连接在一起。

我想删除表 blob 中在表 files.id 中找不到 fileid 的所有行。

因此,使用上面的示例将删除 blob 表中的行:3 和 4(s)。

【问题讨论】:

  • 如果您使用的是nulls,请跳至第二个答案

标签: sql mysql


【解决方案1】:

使用 LEFT JOIN/IS NULL:

DELETE b FROM BLOB b 
  LEFT JOIN FILES f ON f.id = b.fileid 
      WHERE f.id IS NULL

使用不存在:

DELETE FROM BLOB 
 WHERE NOT EXISTS(SELECT NULL
                    FROM FILES f
                   WHERE f.id = fileid)

使用 NOT IN:

DELETE FROM BLOB
 WHERE fileid NOT IN (SELECT f.id 
                        FROM FILES f)

警告

尽可能在事务中执行 DELETE(假设支持 - IE:不在 MyISAM 上),以便在出现问题时使用回滚恢复更改。

【讨论】:

  • 这通常是上述最快的?
  • 由于某种原因,使用 LEFT JOIN 删除在 MS SQL Server Mgmt Studio 上不起作用(不知道为什么;它只是抱怨 LEFT JOIN)。有谁知道这是为什么?它虽然使用 NOT EXISTS 工作:)
  • 仅供参考,这里对这三种方法的相对效率进行了有用的讨论:explainextended.com/2009/09/18/…
  • @Pacerier - “错误”有点强烈。为确保人们理解,如果fileid不可为空,答案确实有效。此外,第三种解决方案 (NOT IN) 仅要求 f.id 不可为空。大概这是一个主键,所以它会。
  • 对于尝试使用 SQLite 进行此操作的人:请参阅 this answer
【解决方案2】:
DELETE FROM blob 
WHERE fileid NOT IN 
       (SELECT id 
        FROM files 
        WHERE id is NOT NULL/*This line is unlikely to be needed 
                               but using NOT IN...*/
      )

【讨论】:

  • 什么是 "/*这行不太可能需要但使用 NOT IN...*/" 应该是什么意思?
  • @Pacerier - NOT IN (NULL) 返回一个空结果集,因此需要排除 NULL。但是id 列可能无论如何都不能为空,因此“不太可能需要”
  • @bunkerdive 然后使用包含数据库名称的三部分对象名称。
  • @Pacerier - 重要的句子是“这条线不太可能需要”。 id 传统上是不可为空的主键。
【解决方案3】:
DELETE FROM blob
WHERE NOT EXISTS (
    SELECT *
    FROM files
    WHERE id=blob.id
)

【讨论】:

  • 我认为有files.idblob.fileid。我猜你的查询会出错。
猜你喜欢
  • 2021-11-02
  • 1970-01-01
  • 2020-09-16
  • 1970-01-01
  • 2011-06-25
  • 1970-01-01
  • 1970-01-01
  • 2010-09-18
相关资源
最近更新 更多