Sql 删除Access中不匹配的记录

Sql 删除Access中不匹配的记录,sql,ms-access,Sql,Ms Access,我在Access数据库中有一个表,其中记录可以从其他两个表中的任何一个引用。我需要从该表中删除没有被其他任何一个引用的记录。 到目前为止,我最好的解决方案是创建一个子查询来返回被引用记录的id,并从删除查询中引用子查询。(子查询必须是独立的,因为Access不允许嵌套子查询中的并集。) 所以… 选择查询: SELECT TableB.id FROM TableB INNER JOIN TableA ON TableB.id = TableA.id UNION SELECT TableC.

我在Access数据库中有一个表,其中记录可以从其他两个表中的任何一个引用。我需要从该表中删除没有被其他任何一个引用的记录。 到目前为止,我最好的解决方案是创建一个子查询来返回被引用记录的id,并从删除查询中引用子查询。(子查询必须是独立的,因为Access不允许嵌套子查询中的并集。)

所以…
选择查询:

SELECT TableB.id FROM TableB INNER JOIN TableA ON TableB.id = TableA.id  
UNION  
SELECT TableC.id FROM TableC INNER JOIN TableA ON TableC.id = TableA.id  
删除查询:

 DELETE * FROM TableA WHERE id NOT IN (SELECT * FROM SelectQuery)
这太慢了。。。一定有更好的办法吗


我试图避免将布尔“
Used
”字段添加到TableA…

基于SelectQuery创建新表、删除原始表并将新表重命名为原始名称是否可以接受?

为什么不这样做:

DELETE FROM TableA 
WHERE 
    id NOT IN (SELECT id FROM TableB)
AND
    id NOT IN (SELECT id FROM TableC)

@Matthew PK建议使用两个NOT IN子查询,这在理论上是一个好主意,但正如我在评论中所观察到的,NOT IN和NOT EXISTS在Jet/ACE中的优化效果不佳,通常不会在比较的两侧使用索引。我想知道是否需要子查询:

  DELETE *
  FROM (TableA LEFT JOIN TableB ON TableA.ID = TableB.ID) LEFT JOIN TableC ON TableA.ID = TableC.ID
  WHERE TableB.ID Is Null AND TableC.ID Is Null;

这肯定会用到你的索引。如果需要子查询,可以用相关的子查询替换TableB和TableC。

最后,我咬了一口,在表a中添加了一个用过的列。用两个单独的查询更新了用过的列,一个用于其他表。然后删除所有已使用的记录=否。将执行时间从56分钟减少到3秒。56分钟?即使您没有索引,并且正在进行三次完整的表扫描,我也很难相信它会花费这么长的时间?是否每个记录都重复整个表的嵌套子查询?对于one.Hmmm,UNION不能使用索引。如果不是我在上面的评论中描述的那样,我很可能已经尝试过了。现在这只是学术兴趣,我没有时间去看。无论如何,谢谢你的想法。问题是Jet/ACE对NOT IN和NOT进行了糟糕的优化,因此它不一定会利用比较两侧的索引。@David,我同意,你的答案比我的好。结合空检查的外部联接绝对是“NOT IN”逻辑的最佳方式+1.我必须更改第一行以删除TableA。*才能在Access查询中使用它
/* delete more records */

DELETE FROM table1
WHERE NOT EXISTS
(SELECT field FROM table2 WHERE table2.field = table1.field)