我有一个嵌入了 Flash 游戏的 Drupal 网站。
已注册的网站用户列在drupal_users表中——这里是一周前注册的列表:
# select uid, created from drupal_users where
to_timestamp(created) < (now() - interval '7 days') limit 5;
uid | created
------+------------
9903 | 1300257067
9904 | 1300259929
9750 | 1299858284
9751 | 1299858603
8083 | 1285514989
(5 rows)
Flash 游戏用户 列在另一个表中 - pref_users 并在他们的 ID 前加上“DE”字符串:
# select id from pref_users where id like 'DE%' limit 5;
id
--------
DE9054
DE9055
DE9056
DE9057
DE9058
(5 rows)
我想摆脱(可能是垃圾邮件机器人)一周前在我的网站上注册但仍未玩过 Flash 游戏的用户。 IE。我想删除 pref_users 表中不存在的 drupal_users 记录。
同时我不想做这样的事情:
# delete from drupal_users where
to_timestamp(created) < (now() - interval '7 days') and
'DE'||uid not in (select id from pref_users where id like 'DE%');
因为我不确定,上面的 select 语句允许有多大(也许有限制?我使用的是 PostgreSQL 8.4.7 和 CentOS 5.5/64 位。在 Drupal7 之前我使用的是 phpBB3,有时我曾在从 phpBB3 管理控制台删除旧论坛帖子时看到此类 SQL 语句失败。
所以我的问题是,如果上面的语句可以重写为some kind of SQL-join ?
最佳答案
在处理具有数百万条记录的表之间的联接时,使用 NOT IN
无法获得可接受的性能。
相反,我写了相当于:
alter table drupal_users add column dont_delete boolean;
然后
update drupal_users set dont_delete = true from pref_users
where 'DE'||drupal_users.uid = pref_users.id.
一旦创建了新的 drupal_users,这将不再有效,但是因为您只是删除超过 7 天的记录,所以没关系。 最后,验证您的记录并发布:
delete from drupal_users where dont_delete is null
and to_timestamp(drupal_users.created) < (now() - interval '7 days');
清理:
alter table drupal_users drop column dont_delete;
关于PostgreSQL 加入 : delete records present in one table, 但不是另一个,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5563716/