我在查找此方案的查询时遇到问题。我想在这个查询中使用两个表,它们是这样的:
Units
ID
Other Data
People
ID
UnitID <-- fk to Units
Other Data
这就是我想要做的事:
我想选择链接到People表中没有行的所有单元。我怎么能这样做?
答案 0 :(得分:8)
SELECT Units.* FROM Units LEFT JOIN People ON People.UnitID = Units.ID WHERE People.ID IS NULL
或者
SELECT Units.* FROM Units WHERE NOT EXISTS (SELECT 1 FROM People WHERE People.UnitID = Units.ID)
甚至
SELECT Units.* FROM Units WHERE Units.ID NOT IN (SELECT UnitID FROM People)
答案 1 :(得分:3)
SELECT * FROM Units
WHERE NOT EXISTS
(SELECT * FROM People WHERE UnitID = Units.ID)
答案 2 :(得分:2)
SELECT * FROM Units
WHERE ID NOT IN (SELECT UnitID FROM People)
答案 3 :(得分:1)
您可以使用not in(选择...)
SELECT ID
FROM Units
WHERE ID NOT IN (SELECT UnitID FROM People);
答案 4 :(得分:1)
SELECT U.*
FROM Units U
WHERE NOT EXISTS (
SELECT 1
FROM People P
WHERE U.ID = P.UnitID
)
请注意,这称为(反)半连接。它是一个实际的连接,不是相关的子查询。
常用的另一种方法是:
SELECT U.*
FROM
Units U
LEFT JOIN People P ON U.ID = P.UnitID
WHERE
P.UnitID IS NULL
请注意,关于联接的其他条件(假设您只想加入活跃的人)需要在join子句中。说WHERE P.UnitID IS NULL AND P.Active = 1
无效。
根据我的经验,根据所选择的实际执行计划,每个不同的查询都可以证明是性能优胜者。引擎使用统计信息预测行数的方式可以使其为某些查询选择次优执行计划,即使统计信息已正确更新也是如此。
注意:在半连接中使用“SELECT 1”而不是“SELECT *”将在查询编译期间保存一些循环,因为*实际上扩展到列列表,然后删除。