以下查询的Not In子句的等效join子句

时间:2018-11-18 16:19:28

标签: sql-server tsql

我有以下查询

select 
    'Un-contacted Cases'as Header, COUNT(a.Id) as Nos,
    ISNULL(SUM(convert(decimal(18, 2), (isnull(PRINCIPAL_OD, 0)))), 0) as Amt
from 
    LoanAccounts a 
where
    a.Id not in (select b.AccountId  
                 from Feedback b 
                 where OutcomeCurrentAction in ('ptp','Contact new PTP','Contact- No new PTP','Contact- No PTP','Met-No-PTP','New PTP','Payment/Direct Deposit') 
                )

这将返回以下输出:

Header              Nos      Amt
----------------------------------------
Un-contacted Cases  1149    131942525.00

但是,当尝试使用左联接编写相同的查询时,我得到了不同的输出

select  
    'Un-contacted Cases' as Header, COUNT(a.Id) as Nos,
    ISNULL(SUM(convert(decimal(18, 2), (isnull(PRINCIPAL_OD, 0)))), 0) as Amt
from 
    LoanAccounts a 
left join 
    Feedback b on b.AccountId = a.Id 
where 
    OutcomeCurrentAction in ('ptp','Contact new PTP','Contact- No new PTP','Contact- No PTP','Met-No-PTP','New PTP','Payment/Direct Deposit') 

这将返回以下输出:

Header              Nos      Amt
---------------------------------------
Un-contacted Cases  51      6026486.00

什么是上述Not In-的等效JOIN?

3 个答案:

答案 0 :(得分:1)

它看起来像:

select 'Un-contacted Cases'as Header, COUNT(a.Id) as Nos,
       COALESCE(SUM(convert(decimal(18, 2), PRINCIPAL_OD)), 0) as Amt
from LoanAccounts a left join
     Feedback b
     on b.AccountId = a.Id and 
        b.OutcomeCurrentAction 
     in ('ptp','Contact new PTP','Contact- No new PTP','Contact- No PTP','Met-No-PTP','New PTP','Payment/Direct Deposit') 
where b.AccountId is null;

我还修复了您的SUM()。您的版本比必要的更为复杂。我实际上认为您确实想要:

       convert(decimal(18, 2) coalesce(sum(PRINCIPAL_OD), 0) as Amt

对小数点进行算术运算时,最好在算术运算符之后转换 -如果这是您真正想要的数据类型。

答案 1 :(得分:1)

您可以尝试以下操作

select 'Un-contacted Cases'as Header, COUNT(a.Id) as Nos,ISNULL(SUM(convert(decimal(18,2),(isnull(PRINCIPAL_OD,0)))),0) as Amt
from LoanAccounts a
left join
(
select b.AccountId  from Feedback b 
    where   OutcomeCurrentAction in ('ptp','Contact new PTP','Contact- No new PTP','Contact- No PTP','Met-No-PTP','New PTP','Payment/Direct Deposit') 
) a1 on a.Id =a1.AccountId  
  where a1.AccountId  is null

答案 2 :(得分:1)

如果对表b执行左连接,则不能在表b的行中将过滤器放入where子句中(除非要查找空值)。 实际上,where子句会将您的左联接变成内部联接,因为表b中不存在的行将始终具有空字段值。

因此,您需要将where子句内容放入左连接条件。像这样:

select  
'Un-contacted Cases' as Header, COUNT(a.Id) as Nos,
ISNULL(SUM(convert(decimal(18, 2), (isnull(PRINCIPAL_OD, 0)))), 0) as Amt
from 
LoanAccounts a 
left join 
Feedback b on b.AccountId = a.Id 
and
b.OutcomeCurrentAction in ('ptp','Contact new PTP','Contact- No new PTP','Contact- No PTP','Met-No-PTP','New PTP','Payment/Direct Deposit')
where b.AccountId is null

这与Gordon的答案基本相同,只是为了解释原因