选择所有没有孩子的实体 - 获得大量行,这是正确的吗?

时间:2014-02-06 00:01:00

标签: sql sql-server

我的Users表中有84,000行。用户是自动创建的。所以,我认为看到有多少用户在创建后实际做了什么就好了。我写了这个问题:

SELECT COUNT(*) FROM Users u
JOIN Folders f ON UserId = u.Id
JOIN Playlists p ON FolderId = f.Id
WHERE 0 = (SELECT COUNT(*) FROM PlaylistItems WHERE PlaylistId = p.Id) 

我的目的是只计算任何播放列表中没有播放列表项的用户。此查询返回了74,000个结果,这似乎很高。

我想知道这个查询是否选择了至少有一个没有项目的播放列表的所有用户。也就是说,如果用户有两个播放列表 - 一个是空的,一个是填充的 - 它们是否仍然在我的查询中计算?并且,如果是这样,我如何修改它以仅选择仅具有空播放列表的用户。

如果这样的话要困难得多,那么我可以尝试只计算一个空的播放列表的用户。

数据库结构是:

  • 很多用户。 1:1用户:文件夹,1:多个文件夹:播放列表,1:多个播放列表:playlistItems

2 个答案:

答案 0 :(得分:1)

比计算每个播放列表更好的模式,比较只是查找在任何播放列表中没有任何内容的所有用户。我喜欢NOT EXISTS

SELECT COUNT(u.Id)
  FROM dbo.Users AS u
  WHERE NOT EXISTS 
  (
    SELECT 1 FROM dbo.PlayLists AS pl
     INNER JOIN dbo.PlayListItems AS pli
     ON pl.id = pli.PlayListID
     INNER JOIN dbo.Folders AS f
     ON p.FolderID = f.ID
     WHERE f.UserID = u.Id
  );

顺便说一下,在其主表中调用列Id以及其他地方的其他地方可能看起来是个好主意,但我觉得它很混乱。为什么在数据模型中到处都没有名为FolderID的FolderID?

答案 1 :(得分:0)

细分查询:

SELECT u.id, COUNT(*) FROM Users u
JOIN Folders f ON UserId = u.Id
JOIN Playlists p ON FolderId = f.Id
join  PlaylistItems on PlaylistId = p.Id
group by u.id

这应该通过userID为您提供所有用户的列表和播放列表中的行数。还有几种方法......

计算不在该列表中的所有用户:

select count(*) from users where id not in (SELECT u.id FROM Users u
JOIN Folders f ON UserId = u.Id
JOIN Playlists p ON FolderId = f.Id
join  PlaylistItems on PlaylistId = p.Id
group by u.id)

MySQL在使用左连接时表现不佳......

 select count(*) 
from   users u left join  (SELECT u.id, COUNT(*) FROM Users u
JOIN Folders f ON UserId = u.Id
JOIN Playlists p ON FolderId = f.Id
join  PlaylistItems on PlaylistId = p.Id
group by u.id)a 
on a.id = u.id
where a.id is null