【问题标题】:Efficiently deleting rows from one table where not matching another [MySQL]有效地从一个表中删除与另一个表不匹配的行 [MySQL]
【发布时间】:2020-09-16 09:41:14
【问题描述】:

所以,我有两个表,用户和积分。很多用户不再有积分(字面意思和表格)——所以我希望删除它们。我尝试通过这样做来实现这一点,但它基本上会超时(两个表中大约有十万行)。我正在选择而不是删除,因为我想在发出与删除相同的查询之前验证数据:

SELECT WWW t1 
FROM users t1
JOIN points t2 ON t1.id != t2.user_id;

两个表都有一个相互匹配的 ID。如果用户有一个点,就会有一个匹配的 ID。如果该用户不再有积分,则没有匹配的 ID。因此,!=理论上应该删除所有不再需要的用户。

如何在不使数据库超时的情况下做到这一点?

【问题讨论】:

标签: mysql sql join query-optimization sql-delete


【解决方案1】:

我会推荐not exists

delete from users
where not exists (select 1 from points p where p.user_id = users.id)

如果您有正确的索引,这应该是一个有效的选择,即:points(user_id)

另一方面,如果您要删除大部分表,将要保留的行移动到临时表中,然后截断并重新创建表可能会更简单:

create table tmp_users as 
select u.*
from users
where exists(select 1 from points p where p.user_id = u.id)

truncate table users;  -- back it up first!

insert into users select * from tmp_users;

drop table tmp_users;

【讨论】:

  • 信息量不是很大。在备份复制服务器上,我尝试了第一个查询并收到此错误:“#1064 - 您的 SQL 语法有错误;请查看与您的 MySQL 服务器版本相对应的手册,以了解在 'u 附近使用的正确语法存在(从点 p 中选择 1,其中 p.user_id = u.id)'在第 1 行“。我不确定 select 1 到底做了什么。
  • @Natsu:似乎 MySQL 在 8.0 版之前的 delete 语句中不支持表别名。我更新了答案中的第一个查询,请试一试。
  • 谢谢!那好多了,当你原来的那个不起作用时,我尝试了类似的东西,但我还是有点不对劲。我在 SQL Server 和 MySQL 之间分道扬镳,有时我会感到困惑。我很感激!
猜你喜欢
  • 2021-11-02
  • 1970-01-01
  • 1970-01-01
  • 2011-03-23
  • 1970-01-01
  • 2020-03-09
  • 1970-01-01
  • 2011-06-25
  • 2011-08-15
相关资源
最近更新 更多