【问题标题】:Why same EXISTS returns different result为什么相同的 EXISTS 返回不同的结果
【发布时间】:2017-04-01 03:48:04
【问题描述】:

每个PolicyNumber 可以有多个ClassCode。所以目标是消除整个PolicyNumber 与所有相关列 如果至少有一个ClassCode 选择被淘汰,则包括所有ClassCode's。 我有cte1PolicyNumberWrittenPremium(WP),我有表tblClassCodesPlazaCommercialPolicyNumberClassCode。 在我的WHERE 子句中我选择:

WHERE       EXISTS (
                    SELECT  DISTINCT PolicyNumber 
                    FROM    tblClassCodesPlazaCommercial 
                    WHERE   PolicyNumber NOT IN (SELECT  PolicyNumber FROM tblClassCodesPlazaCommercial WHERE  ClassCode =5151)
                    )

如果我 select * from cte3 WHERE ClassCode =5151 我仍然有 ClassCode 5151 的策略

下面的整个select语句:

 select     
                cte1.PolicyNumber,
                cte1.TransactionEffectiveDate,
                cc.ClassCode,
                CASE
                    WHEN ROW_NUMBER() OVER (PARTITION BY cte1.QuoteID, cte1.PolicyNumber, cc.TransactionEffectiveDate ORDER BY (SELECT 0))=1 THEN cte1.WP 
                    ELSE 0
                END  as WP--,
    from        cte1 inner join tblClassCodesPlazaCommercial cc on cte1.PolicyNumber=cc.PolicyNumber AND cte1.QuoteID=cc.QuoteID AND cte1.TransactionEffectiveDate=cc.TransactionEffectiveDate 
    where       EXISTS (SELECT DISTINCT PolicyNumber FROM tblClassCodesPlazaCommercial WHERE PolicyNumber NOT IN (SELECT  PolicyNumber FROM tblClassCodesPlazaCommercial WHERE  ClassCode =5151))

但是,如果我用没有 ClassCode 5151 的 PolicyNumber 声明 @PoliciesThatDontHaveClassCodes 表并在我的 EXISTS 命令中使用它 - 那么它就可以工作。

DECLARE @PoliciesThatDontHaveClassCodes Table (PolicyNumber varchar(100)) 
INSERT INTO @PoliciesThatDontHaveClassCodes SELECT DISTINCT PolicyNumber    FROM tblClassCodesPlazaCommercial 
                                                                            WHERE PolicyNumber NOT IN (SELECT  PolicyNumber FROM tblClassCodesPlazaCommercial WHERE  ClassCode =5151)
select      
            cte1.PolicyNumber,
            cte1.TransactionEffectiveDate,
            cc.ClassCode,
            CASE
                WHEN ROW_NUMBER() OVER (PARTITION BY cte1.QuoteID, cte1.PolicyNumber, cc.TransactionEffectiveDate ORDER BY (SELECT 0))=1 THEN cte1.WP 
                ELSE 0
            END  as WP--,
from        cte1 inner join tblClassCodesPlazaCommercial cc on cte1.PolicyNumber=cc.PolicyNumber 
            AND cte1.QuoteID=cc.QuoteID 
            AND cte1.TransactionEffectiveDate=cc.TransactionEffectiveDate 
where       EXISTS (SELECT * FROM @PoliciesThatDontHaveClassCodes t  WHERE t.PolicyNumber=cc.PolicyNumber )

有什么区别?两个子查询本身返回完全相同的结果集。为什么在第一种情况下它不起作用,但在第二种情况下(当我声明@PoliciesThatDontHaveClassCodes 时) - 它起作用了? 如何在不声明任何表变量的情况下获得相同的结果?

【问题讨论】:

  • 但不一样。其中一个是NOT IN (SELECT....),另一个是不同的条件。第二个查询实际上是将EXISTS 的结果与外部表相关联,第一个查询只是查看是否存在任何行......并且由于它确实存在,因此外部表中的每个结果都是如此

标签: sql-server tsql exists notin


【解决方案1】:

在您提供的第一个示例中

WHERE EXISTS (SELECT  DISTINCT PolicyNumber 
                FROM    tblClassCodesPlazaCommercial 
                WHERE   PolicyNumber NOT IN (SELECT  PolicyNumber 
                                               FROM tblClassCodesPlazaCommercial 
                                               WHERE  ClassCode =5151))

外部查询和子查询之间没有关联。因此,我们单独评估子查询,并且由于查询返回一行,因此WHERE EXISTS … 始终为真。

在第二个示例中,您将子查询与外部查询相关联,这就是 t.PolicyNumber = cc.PolicyNumber 所做的,因为 cc 在子查询之外:

WHERE EXISTS (SELECT * FROM @PoliciesThatDontHaveClassCodes t  
               WHERE t.PolicyNumber=cc.PolicyNumber )

因此,对于外部查询的每一行,子查询的结果(可能)都不同。

因此,两个WHERE 子句的计算方式不同。

编辑

第一个谓词的可能修改

WHERE NOT EXISTS (Select 1 From tblClassCodesPlazaCommercial As t
                           Where t.PolicyNumber = cc.PolicyNumber
                             And t.ClassCode = 5151)

【讨论】:

  • 哦,知道了。谢谢。那么我将如何重写第一个?有可能吗?
  • @Oleg 查看使用LEFT ANTI SEMI JOIN sqlity.net/en/1360/a-join-a-day-the-left-anti-semi-join的更新答案
  • @Oleg 如果此答案解决了您的问题,请接受。
  • 确实如此。为......感到抱歉。并感谢您的精彩解释!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-10-17
  • 2012-07-28
  • 2013-03-10
  • 1970-01-01
  • 2016-08-30
  • 2020-10-12
  • 1970-01-01
相关资源
最近更新 更多