【问题标题】:Subquery returning more than one result?子查询返回多个结果?
【发布时间】:2023-04-09 20:51:02
【问题描述】:

我运行这个查询:

SELECT 
        CAST(PolicyNumber AS varchar(50)) POLICYNUMBER,
        CAST(EFFECTIVEDATE AS DATE) EFFECTIVEDATE ,
        MAX(CAST(EXPIRATIONDATE AS DATE)) EXPIRATIONDATE,
        CAST(ISSUINGCOMPANY AS varchar(4)) AS INSURER,
        CAST(INSUREDLEGALNAME AS varchar(250)) AS INSUREDNAME,
        PROGRAM,
        MAX(CAST(CANCELDATE AS DATE)) AS CANCELDATE,        
        CAST(INSUREDADDR1 AS varchar(500)) AS INSUREDADDR1,
        CAST(INSUREDADDR2 AS varchar(500)) AS INSUREDADDR2,
        CAST(INSUREDCITY AS varchar(500)) AS INSUREDCITY,
        CAST(INSUREDSTATE AS varchar(20)) AS INSUREDSTATE,
        CAST(INSUREDZIP AS varchar(20)) AS INSUREDZIP   ,
        (SELECT SourceId FROM STG.[Source] WHERE [SystemName] = 'CRU') AS SOURCESYSTEMID    
        ,(Select  ProgramInclude = CASE WHEN ProgramInClude = 'Y' THEN 1 Else 0 END  
         From STG.LPT L INNER Join SRC.Policy C ON C.Program = L.ProgramCode  ) AS LPT
     FROM SRC.Policy  

     GROUP BY POLICYNUMBER,
     EFFECTIVEDATE,
     ISSUINGCOMPANY,
     INSUREDLEGALNAME,
     PROGRAM,
     INSUREDADDR1,
     INSUREDADDR2,
     INSUREDCITY,
     INSUREDSTATE,
     INSUREDZIP

得到这个结果:

消息 512,第 16 级,状态 1,第 16 行 子查询返回超过 1 个值。当子查询跟随 =、!=、、>= 或子查询用作表达式时,这是不允许的。 警告:空值被聚合或其他 SET 操作消除。

有什么想法吗?

【问题讨论】:

  • 是的,您的子查询返回多个结果...错误非常明确。
  • @DaleK 感谢您的回复,但您能提出一些解决方案吗?
  • 只有您知道您的数据库,您使用的 2 个子查询中的 1 个未返回唯一结果。检查你的逻辑,找出为什么你会得到重复,并决定如何避免它。在没有看到您的数据或不了解您的业务逻辑的情况下,我们无法修复它。
  • 对于LPT,您的查询不引用外部查询。我很确定这是你的错误。
  • 这个(Select ProgramInclude = CASE WHEN ProgramInClude = 'Y' THEN 1 Else 0 END From STG.LPT L INNER Join SRC.Policy C ON C.Program = L.ProgramCode ) 没有where 子句,这很可能是问题所在。

标签: sql sql-server tsql ssms-2016


【解决方案1】:

您的子查询应该只返回一行,因为它们是您的结果集的一部分。你可以做的是:

  • 要么确保 WHERE 子句确保只返回一行
  • 添加 TOP 1 子句以确保只返回一行。添加 TOP 子句时,添加 ORDER BY 子句以确保您确定地获取数据,而不是随机获取数据。因为我没有你的架构,所以我没有为子查询添加 ORDER BY
  • 另外,您不需要在子查询中再加入一次。您可以在子查询中引用外部 Policy 表
    SELECT 
            CAST(PolicyNumber AS varchar(50)) POLICYNUMBER,
            CAST(EFFECTIVEDATE AS DATE) EFFECTIVEDATE ,
            MAX(CAST(EXPIRATIONDATE AS DATE)) EXPIRATIONDATE,
            CAST(ISSUINGCOMPANY AS varchar(4)) AS INSURER,
            CAST(INSUREDLEGALNAME AS varchar(250)) AS INSUREDNAME,
            PROGRAM,
            MAX(CAST(CANCELDATE AS DATE)) AS CANCELDATE,        
            CAST(INSUREDADDR1 AS varchar(500)) AS INSUREDADDR1,
            CAST(INSUREDADDR2 AS varchar(500)) AS INSUREDADDR2,
            CAST(INSUREDCITY AS varchar(500)) AS INSUREDCITY,
            CAST(INSUREDSTATE AS varchar(20)) AS INSUREDSTATE,
            CAST(INSUREDZIP AS varchar(20)) AS INSUREDZIP   ,
            (SELECT TOP 1 SourceId FROM STG.[Source] WHERE [SystemName] = 'CRU') AS SOURCESYSTEMID    
            ,(Select TOP 1 ProgramInclude = CASE WHEN ProgramInClude = 'Y' THEN 1 Else 0 END  
             From STG.LPT L WHERE L.ProgramCode = op.Program  ) AS LPT
         FROM SRC.Policy  AS op

         GROUP BY POLICYNUMBER,
         EFFECTIVEDATE,
         ISSUINGCOMPANY,
         INSUREDLEGALNAME,
         PROGRAM,
         INSUREDADDR1,
         INSUREDADDR2,
         INSUREDCITY,
         INSUREDSTATE,
         INSUREDZIP

上面那个,你必须确保你的 TOP 子句返回正确的那个。否则,我会建议另一种避免子查询和使用 JOINS 的选项,如下所述:

DECLARE @SourceId INT 
-- Use either of the below approaches for populating @sourceId

SET @SourceId = (SELECT SourceId FROM STG.[Source] WHERE [SystemName] = 'CRU' ) -- Add additional WHERE clause to pickup right value or

SET @SourceId = (SELECT TOP 1 SourceId FROM STG.[Source] WHERE [SystemName] = 'CRU' ) -- Add additional ORDER BY clause. 

    SELECT 
            CAST(PolicyNumber AS varchar(50)) POLICYNUMBER,
            CAST(EFFECTIVEDATE AS DATE) EFFECTIVEDATE ,
            MAX(CAST(EXPIRATIONDATE AS DATE)) EXPIRATIONDATE,
            CAST(ISSUINGCOMPANY AS varchar(4)) AS INSURER,
            CAST(INSUREDLEGALNAME AS varchar(250)) AS INSUREDNAME,
            PROGRAM,
            MAX(CAST(CANCELDATE AS DATE)) AS CANCELDATE,        
            CAST(INSUREDADDR1 AS varchar(500)) AS INSUREDADDR1,
            CAST(INSUREDADDR2 AS varchar(500)) AS INSUREDADDR2,
            CAST(INSUREDCITY AS varchar(500)) AS INSUREDCITY,
            CAST(INSUREDSTATE AS varchar(20)) AS INSUREDSTATE,
            CAST(INSUREDZIP AS varchar(20)) AS INSUREDZIP   ,
            @SourceId AS SOURCESYSTEMID,    
            CASE WHEN ProgramInClude = 'Y' THEN 1 Else 0 END AS LPT
         FROM SRC.Policy  AS op
         INNER JOIN STG.LPT L ON 
         L.ProgramCode = op.Program
         GROUP BY POLICYNUMBER,
         EFFECTIVEDATE,
         ISSUINGCOMPANY,
         INSUREDLEGALNAME,
         PROGRAM,
         INSUREDADDR1,
         INSUREDADDR2,
         INSUREDCITY,
         INSUREDSTATE,
         INSUREDZIP,
         @SourceId AS SOURCESYSTEMID,
         CASE WHEN ProgramInClude = 'Y' THEN 1 Else 0 END 

【讨论】:

  • 使用TOP 1 的危险在于它会在逻辑错误时隐藏此错误,如问题中所示。就我个人而言,我不会用它来强迫我正确查询。
  • 知道了。我会用另一个选项更新我的答案
【解决方案2】:

我已经对自己进行了一些修改,结果如下,现在运行良好。而且我没有使用TOP 1,而是更正了子查询中不必要的连接

谢谢大家的帮助。

SELECT 
        CAST(PolicyNumber AS varchar(50)) POLICYNUMBER,
        CAST(EFFECTIVEDATE AS DATE) EFFECTIVEDATE ,
        MAX(CAST(EXPIRATIONDATE AS DATE)) EXPIRATIONDATE,
        CAST(ISSUINGCOMPANY AS varchar(4)) AS INSURER,
        CAST(INSUREDLEGALNAME AS varchar(250)) AS INSUREDNAME,
        PROGRAM,
        MAX(CAST(CANCELDATE AS DATE)) AS CANCELDATE,        
        CAST(INSUREDADDR1 AS varchar(500)) AS INSUREDADDR1,
        CAST(INSUREDADDR2 AS varchar(500)) AS INSUREDADDR2,
        CAST(INSUREDCITY AS varchar(500)) AS INSUREDCITY,
        CAST(INSUREDSTATE AS varchar(20)) AS INSUREDSTATE,
        CAST(INSUREDZIP AS varchar(20)) AS INSUREDZIP   ,
        (SELECT SourceId FROM STG.[Source] WHERE [SystemName] = 'CRU') AS SOURCESYSTEMID    
        ,(Select  ProgramInclude = CASE WHEN ProgramInClude = 'Y' THEN 1 Else 0 END  
         From STG.LPT L WHERE C.Program = L.ProgramCode  ) AS LPT
     FROM SRC.CRUPolicy  C

     GROUP BY POLICYNUMBER,
     EFFECTIVEDATE,
     ISSUINGCOMPANY,
     INSUREDLEGALNAME,
     PROGRAM,
     INSUREDADDR1,
     INSUREDADDR2,
     INSUREDCITY,
     INSUREDSTATE,
     INSUREDZIP

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-25
    • 2020-10-23
    • 2020-11-25
    • 2015-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-30
    相关资源
    最近更新 更多