在下面的SQL中,@UserExtendedSecurity
是一个表变量,根据用户是否具有扩展安全性,它只提供1或0指示符:
INSERT INTO @UserExtendedSecurity (UserId, UserName, HasExtendedSecurity)
SELECT
ue.Id,
adu.FirstName + ' ' + adu.LastName,
0
FROM
UserExtension ue
JOIN
ADUser adu ON ue.ADUserId = adu.Id
WHERE
ue.Id NOT IN (SELECT UserId FROM @UserExtendedSecurity)
在上面的SQL示例中,@UserExtendedSecurity
已经拥有HasExtendedSecurity = 1
的所有用户,因此我只是将剩余的用户选择到表变量中,HasExtendedSecurity
值为0。最后NOT IN
条款做了它需要做的事情,但有没有更合适/优雅/有效的方法来完成我正在做的事情? SQL专家是否考虑以这种方式使用NOT IN
作为红旗?
答案 0 :(得分:0)
令人惊讶的是,NOT EXISTS
实际上可以获得更好的性能。请注意,行为略有不同 - 使用空值可以更好地工作(有关详细信息,请参阅this question)。
INSERT INTO @UserExtendedSecurity
(
UserId,
UserName,
HasExtendedSecurity
)
SELECT
ue.Id,
adu.FirstName + ' ' + adu.LastName,
0
FROM
UserExtension ue
JOIN ADUser adu ON ue.ADUserId = adu.Id
WHERE NOT EXISTS
( SELECT 0 FROM @UserExtendedSecurity WHERE UserId = ue.Id)
答案 1 :(得分:0)
基本上你有3个选择:
(是;博士; -
所有选项都是有效的,并且所有选项都有正确的用法 - 但总的来说,我宁愿大多数时间都使用not exists
。)
NOT IN
SELECT
ue.Id,
adu.FirstName + ' ' + adu.LastName,
0
FROM
UserExtension AS ue
JOIN
ADUser AS adu ON ue.ADUserId = adu.Id
WHERE
ue.Id NOT IN (SELECT UserId FROM @UserExtendedSecurity)
优点:
缺点:
null
处理。当null
内有NOT IN
时,除非将ansi_nulls设置为关闭(由于它已被弃用,您真的应该避免),否则您将无法获得任何结果x NOT IN(y,NULL)
相当于x <> y and x <> null
- 与null
的任何值相比,包括另一个null
,将返回unknown
。 IN
内部设置较大,则与其他选项相比,性能可能会较慢。NOT EXISTS
SELECT
ue.Id,
adu.FirstName + ' ' + adu.LastName,
0
FROM
UserExtension AS ue
JOIN
ADUser AS adu ON ue.ADUserId = adu.Id
WHERE
NOT EXISTS (SELECT 1 FROM @UserExtendedSecurity WHERE UserId = ue.Id)
优点:
Null
不再是问题。not in
替代方案更好的性能。缺点:
LEFT JOIN
SELECT
ue.Id,
adu.FirstName + ' ' + adu.LastName,
0
FROM
UserExtension AS ue
JOIN
ADUser AS adu ON ue.ADUserId = adu.Id
LEFT JOIN @UserExtendedSecurity AS ues ON ues.UserId = ue.Id
WHERE ues.UserId IS NULL
优点:
Null
值是&#34;自然&#34;处理。not in
替代方案更好的性能。缺点: