我有一张表格,里面包含了用户的所有照片。出于某种原因(不在乎为什么),某些用户可以从用户表中删除(使用DELETE FROM),但照片保留在照片表中。这个MYSQL查询如何更好
我需要知道用户表中实际存在的用户数量。
我想出了第一个解决方案是这样的:
SELECT COUNT(DISTINCT user_id) FROM photos WHERE user_id IN (SELECT id FROM users)
但我不知道,如果做两个查询是最好的一个。有一个更好的方法吗?
我有一张表格,里面包含了用户的所有照片。出于某种原因(不在乎为什么),某些用户可以从用户表中删除(使用DELETE FROM),但照片保留在照片表中。这个MYSQL查询如何更好
我需要知道用户表中实际存在的用户数量。
我想出了第一个解决方案是这样的:
SELECT COUNT(DISTINCT user_id) FROM photos WHERE user_id IN (SELECT id FROM users)
但我不知道,如果做两个查询是最好的一个。有一个更好的方法吗?
这样做的最好方法是在两个表之间使用foriegn键约束,并实现级联删除。提供更多信息在MySQL手册:
http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html
正如评论者所指出的那样,这需要使用InnoDB存储引擎。 This is the default storage engine as of MySQL 5.5.5.
首先,你的查询会不返回由用户添加的照片中实际存在的用户表中的号码 - 而是返回其在至少一个匹配行从用户表的用户数照片表。
这个查询应该是等价的(可能会更好,可能是性能方面更差虽然):
SELECT COUNT(DISTINCT user_id)
FROM photos, users
WHERE photos.user_id = users.id
如果你真的需要存在于用户表的用户添加的照片数量:
SELECT COUNT(*)
FROM photos, users
WHERE photos.user_id = users.id
假设您没有重复的用户标识符。
'count(*)'总是比'count(some_field)'更快。 – Johan 2011-06-01 20:36:11
如果你想知道你有多少个非孤儿图片,你完全不需要DISTINCT
。
SELECT COUNT(*)
FROM users u
INNER JOIN photos p ON (p.user_id = p.id)
使用此sql查询。
SELECT COUNT(*)
FROM photos p
INNER JOIN users u
ON p.user_id = u.user_id
级联删除的MyISAM
为了扩大对AJ的答案。如果你不想改变表格。或者你没有InnoDB表。
您仍然可以级联删除。
放在主导表after delete
触发,并把代码是这样的:
您可以有Y'R鱼和熊掌兼得她太
DELIMITER $$
CREATE TRIGGER ad_users_each AFTER DELETE ON users FOR EACH ROW
BEGIN
DELETE FROM photos WHERE photos.user_id = old.id;
END $$
DELIMITER ;
瞧,在级联删除MyISAM数据。
它是如何工作的?
触发后每个成功删除表用户中的一行。
触发器中的old
虚拟表在其被删除之前的值为users.id
。我使用该ID来查找表photos
中的所有匹配的user_id
,并删除那些已链接到现在已删除的用户的链接。
如果您添加需要InnoDB引擎的其他信息,那将会很好。 – RRStoyanov 2011-06-01 20:03:39
我同意在这里使用foreigns键。但由于某种原因,原来这样做的人并没有使用它们。 – aseba 2011-06-01 20:03:58
@aseba比你做;) – RRStoyanov 2011-06-01 20:05:29