一尘不染

SQL:不存在与不存在奇怪的行为

sql

在我寻找答案的过程中,我似乎只找到了涵盖存在的解释,NULL这就是NOT IN返回 0 结果的原因。然而,我的情况恰恰相反。我得到了我的预期结果,NOT IN而我NOT EXISTS给了我 0。澄清一下,我的子查询中没有 NULL。这是我的查询:

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 处理之外没有真正的区别。

我的期望在哪里出错了?


阅读 79

收藏
2022-07-21

共1个答案

一尘不染

查询形状…

and o.ClinicLocationId not in (SELECT o.ClinicLocationId ...)

…与o.ClinicLocationIdo.ClinicLocationId查询相关。

使用exists时必须编写相关子查询才能获得相同的效果:

and not exists (SELECT o1.ClinicLocationId ...
    AND o1.ClinicLocationId = o.ClinicLocationId)

请注意,第二个查询需要在子查询中使用不同的别名。

2022-07-21