在我寻找答案的过程中,我似乎只找到了涵盖存在的解释,NULL这就是NOT IN返回 0 结果的原因。然而,我的情况恰恰相反。我得到了我的预期结果,NOT IN而我NOT EXISTS给了我 0。澄清一下,我的子查询中没有 NULL。这是我的查询:
NULL
NOT IN
NOT EXISTS
DECLARE @EndDate DATE= CAST(CONCAT(YEAR(GETDATE()), '-', MONTH(GETDATE()), '-01') AS DATE) --First day of this month DECLARE @StartDate DATE= DATEADD(month, -12, @EndDate) --12 months prior SELECT Deactivated = COUNT(DISTINCT o.ClinicLocationId) FROM [order].package p WITH(NOLOCK) INNER JOIN [order].[order] o WITH(NOLOCK) ON o.packageid = p.packageid INNER JOIN profile.ClinicLocationInfo cli WITH(NOLOCK) ON cli.LocationId = o.ClinicLocationId AND cli.FacilityType IN('CLINIC', 'HOSPITAL') WHERE CAST(p.ShipDTM AS DATE) >= dateadd(month,-1,@StartDate) AND CAST(p.ShipDTM AS DATE) < dateadd(month,-1,@EndDate) AND p.isshipped = 1 AND o.IsShipped = 1 AND ISNULL(o.iscanceled, 0) = 0 and not exists ( --and o.ClinicLocationId not in ( SELECT DISTINCT o.ClinicLocationId FROM [order].package p WITH(NOLOCK) INNER JOIN [order].[order] o WITH(NOLOCK) ON o.packageid = p.packageid INNER JOIN profile.ClinicLocationInfo cli WITH(NOLOCK) ON cli.LocationId = o.ClinicLocationId AND cli.FacilityType IN('CLINIC', 'HOSPITAL') WHERE CAST(p.ShipDTM AS DATE) >= @StartDate AND CAST(p.ShipDTM AS DATE) < dateadd(day,-1,@EndDate) AND p.isshipped = 1 AND o.IsShipped = 1 AND ISNULL(o.iscanceled, 0) = 0 )
对于高级概述,我基本上是在尝试查找一组中存在但下一组中不存在的 ID 数量(由 12 个月的滚动窗口分隔,偏移 1 个月)。但是为了简单起见,我在下面写了非常简单地说明了完全相同的症状:
drop table if exists #T1, #T2 create table #T1 (id int) create table #T2 (id int) insert into #T1 (id) values (3), (8) insert into #T2 (id) values (671), (171) select id from #T1 where id not in (select id from #T2) select id from #T1 where not exists (select id from #T2)
我的期望是这两个都会产生相同的结果,即#T1(3,8) 的内容,但是相反,我只在第二个查询中通过消除NOT. 我假设我对EXISTS操作员的工作方式存在根本性的误解,因为到目前为止,我认为除了扫描发生的方式和 NULL 处理之外没有真正的区别。
#T1
NOT
EXISTS
我的期望在哪里出错了?
查询形状…
and o.ClinicLocationId not in (SELECT o.ClinicLocationId ...)
…与o.ClinicLocationId子o.ClinicLocationId查询相关。
o.ClinicLocationId
使用exists时必须编写相关子查询才能获得相同的效果:
exists
and not exists (SELECT o1.ClinicLocationId ... AND o1.ClinicLocationId = o.ClinicLocationId)
请注意,第二个查询需要在子查询中使用不同的别名。