Sql server 使用NOT IN时出现空值问题
我有一个查询,我试图删除所有记录,如果实践和实体的组合只出现一次,并且其中一个记录的状态为“已终止”或“已撤销”,那么我希望将其删除。如果机构/实体有多个记录,且其中至少有一个记录的状态为“非终止/撤销”,则我希望保留这些其他记录。我编写了一个查询来实现这一点,如下所示 但是,我遇到的问题是,查询正在删除空记录。我理解这是因为Exists/NOT IN子句,其中NULL(终止、撤回)的计算结果为UNKNOWN 我尝试以相反的方式编写查询,使用NOT EXISTS/in,但删除了数千条其他记录。有人知道在这种情况下如何包含空值吗Sql server 使用NOT IN时出现空值问题,sql-server,Sql Server,我有一个查询,我试图删除所有记录,如果实践和实体的组合只出现一次,并且其中一个记录的状态为“已终止”或“已撤销”,那么我希望将其删除。如果机构/实体有多个记录,且其中至少有一个记录的状态为“非终止/撤销”,则我希望保留这些其他记录。我编写了一个查询来实现这一点,如下所示 但是,我遇到的问题是,查询正在删除空记录。我理解这是因为Exists/NOT IN子句,其中NULL(终止、撤回)的计算结果为UNKNOWN 我尝试以相反的方式编写查询,使用NOT EXISTS/in,但删除了数千条其他记录。有
declare @tab Table
(practice varchar(100),
entity varchar(100),
assignedto varchar(100),
statusname varchar(50)
)
insert into @tab values ('F&S', 'Sinai', 'AnnM', NULL);
insert into @tab values ('F&S', 'Levin', 'AnnM', NULL);
insert into @tab values ('F&S', 'Hopkins','AnnM', NULL);
select *,
ROW_NUMBER()over(partition by entity, statusname order by entity) as rn
from @tab t1
where exists(select *
from @tab t2
where t1.practice = t2.practice
and t1.entity= t2.entity
and t1.assignedto = t2.assignedto
and t2.statusname not in( 'Withdrawn', 'Terminated'));
您可以将
ISNULL
与伪值一起使用:
select *,
ROW_NUMBER()over(partition by entity, statusname order by entity) as rn
from @tab t1
where exists(select *
from @tab t2
where t1.practice = t2.practice
and t1.entity= t2.entity
and t1.assignedto = t2.assignedto
and ISNULL(t2.statusname, '@@@')
not in( 'Withdrawn', 'Terminated'));
您可以将
ISNULL
与伪值一起使用:
select *,
ROW_NUMBER()over(partition by entity, statusname order by entity) as rn
from @tab t1
where exists(select *
from @tab t2
where t1.practice = t2.practice
and t1.entity= t2.entity
and t1.assignedto = t2.assignedto
and ISNULL(t2.statusname, '@@@')
not in( 'Withdrawn', 'Terminated'));
我宁愿使用
t2。statusname为空
,所以优化器仍然可以使用任何索引
select *,
ROW_NUMBER()over(partition by entity, statusname order by entity) as rn
from @tab t1
where exists(select 1
from @tab t2
where t1.practice = t2.practice
and t1.entity= t2.entity
and t1.assignedto = t2.assignedto
and (t2.statusname IS NULL OR
t2.statusname not in ('Withdrawn', 'Terminated')
)
);
我宁愿使用
t2.statusname为空
,所以优化器仍然可以使用任何索引
select *,
ROW_NUMBER()over(partition by entity, statusname order by entity) as rn
from @tab t1
where exists(select 1
from @tab t2
where t1.practice = t2.practice
and t1.entity= t2.entity
and t1.assignedto = t2.assignedto
and (t2.statusname IS NULL OR
t2.statusname not in ('Withdrawn', 'Terminated')
)
);
最愚蠢的方式:
(t2.statusname不在('dracked','Terminated')或t2.statusname不为NULL)
@LONG这里没有最愚蠢的东西。应该是正确的方法。@JuanCarlosOropeza,哈哈,只是懒洋洋地使用ISNULL
等,就像下面xD的答案一样,谢谢you@LONG您应该用(…或…
括起来以避免混淆其中
包含多个条件:)如果为null,则合并将起作用,但它们不会使用索引。你可以做和不做(t2.statusname in('deculled','Terminated'))最愚蠢的方式:(t2.statusname不in('deculled','Terminated')或t2.statusname不为NULL)
@LONG这里没有最愚蠢的东西。应该是正确的方法。@JuanCarlosOropeza,哈哈,只是懒洋洋地使用ISNULL
等,就像下面xD的答案一样,谢谢you@LONG您应该用(…或…
括起来以避免混淆其中
包含多个条件:)如果为null,则合并将起作用,但它们不会使用索引。您可以执行也可以不执行(t2.statusname in('deculled','Terminated'))t2.statusname不为NULL更好。可以使用index@JuanCarlosOropeza一般来说是(SARGable计数:))。仍然在OP的示例中,有一个表变量,所以它不重要。请不要使用ISNULL<代码>不为空,状态名称不在
中可以利用任何索引<另一方面,code>ISNULL(…)将强制进行完整的表扫描,以便计算结果。表变量可以有主键和索引。我没有使用表变量。我刚刚在这里创建了一个,以便人们可以测试它。t2.statusname不为NULL
更好。可以使用index@JuanCarlosOropeza一般来说是(SARGable计数:))。仍然在OP的示例中,有一个表变量,所以它不重要。请不要使用ISNULL<代码>不为空,状态名称不在中可以利用任何索引<另一方面,code>ISNULL(…)将强制进行完整的表扫描,以便计算结果。表变量可以有主键和索引。我没有使用表变量。我刚刚在这里创建了一个,这样人们就可以测试它了。而不是(t2.statusname in('retracted','Terminated'))将是同一代码的较短版本。这似乎可以工作,谢谢!比我想象的要简单得多。而不是(t2.statusname in('retracted','Terminated')将是同一代码的较短版本。这似乎可行,谢谢!比我想象的简单多了。