2011-06-01 95 views
0

我有一张表格,里面包含了用户的所有照片。出于某种原因(不在乎为什么),某些用户可以从用户表中删除(使用DELETE FROM),但照片保留在照片表中。这个MYSQL查询如何更好

我需要知道用户表中实际存在的用户数量。

我想出了第一个解决方案是这样的:

SELECT COUNT(DISTINCT user_id) FROM photos WHERE user_id IN (SELECT id FROM users) 

但我不知道,如果做两个查询是最好的一个。有一个更好的方法吗?

回答

4

这样做的最好方法是在两个表之间使用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.

+0

如果您添加需要InnoDB引擎的其他信息,那将会很好。 – RRStoyanov 2011-06-01 20:03:39

+0

我同意在这里使用foreigns键。但由于某种原因,原来这样做的人并没有使用它们。 – aseba 2011-06-01 20:03:58

+0

@aseba比你做;) – RRStoyanov 2011-06-01 20:05:29

0

首先,你的查询会返回由用户添加的照片中实际存在的用户表中的号码 - 而是返回其在至少一个匹配行从用户表的用户数照片表。

这个查询应该是等价的(可能会更好,可能是性能方面更差虽然):

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 

假设您没有重复的用户标识符。

+0

'count(*)'总是比'count(some_field)'更快。 – Johan 2011-06-01 20:36:11

1

如果你想知道你有多少个非孤儿图片,你完全不需要DISTINCT

SELECT COUNT(*) 
FROM users u 
INNER JOIN photos p ON (p.user_id = p.id) 
0

使用此sql查询。

SELECT COUNT(*) 
    FROM photos p 
     INNER JOIN users u 
      ON p.user_id = u.user_id 
2

级联删除的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,并删除那些已链接到现在已删除的用户的链接。