【发布时间】:2009-05-26 03:53:50
【问题描述】:
我有 2 张桌子 群体和人
人们的 GroupId 链接到 Group.GroupId(主键)
如何选择没有人的群组?在 t-sql 和 linq 中
谢谢
【问题讨论】:
我有 2 张桌子 群体和人
人们的 GroupId 链接到 Group.GroupId(主键)
如何选择没有人的群组?在 t-sql 和 linq 中
谢谢
【问题讨论】:
更新
我已经通过 SQL Server 2005 运行了四种不同的方法来执行此操作,并包含执行计划。
-- 269 reads, 16 CPU
SELECT *
FROM Groups
WHERE NOT EXISTS (
SELECT *
FROM People
WHERE People.GroupId = Groups.GroupId
);
-- 249 reads, 15 CPU
SELECT *
FROM Groups
WHERE (
SELECT COUNT(*)
FROM People
WHERE People.GroupId = Groups.GroupId
) = 0
-- 249 reads, 14 CPU
SELECT *
FROM Groups
WHERE GroupId NOT IN (
SELECT DISTINCT GroupId
FROM Users
)
-- 10 reads, 12 CPU
SELECT *
FROM Groups
LEFT JOIN Users ON Users.GroupId = Groups.GroupId
WHERE Users.GroupId IS NULL
所以最后一个,虽然可以说是四个中可读性最低的,但表现最好。
这让我感到惊讶,老实说,我仍然更喜欢 WHERE NOT EXISTS 语法,因为我认为它更明确 - 它读起来与您尝试做的完全一样。
【讨论】:
我首选的方法是左反半连接:
SELECT g.*
FROM Groups g
LEFT JOIN People p ON g.GroupID = p.GroupID
WHERE p.GroupID IS NULL
我发现它最直观、最灵活、最高效。
我写了一篇关于各种查询策略来搜索缺失数据的整篇文章 - 如果您有兴趣,请查看 here。
【讨论】:
IS NULL 在mysql 中绝对是一种性能良好的方法(但不确定它在性能方面如何与各种SQL Server 版本中的WHERE NOT EXITS 进行比较)。
我认为最简单的解决方案是:
SELECT *
FROM GROUPS
WHERE GroupId NOT IN (SELECT DISTINCT GroupId FROM People)
【讨论】: