在 SQL Server 2008 R2 中执行 SQL 查询时出错

问题描述 投票:0回答:1

我不是 SQL 开发人员。我正在执行下面的查询,它是 select 语句的子查询。

此特定子查询的查询失败,并出现以下错误。

消息 512,第 16 级,状态 1,第 13 行
子查询返回超过 1 个值。当子查询跟在 =、!=、<, <= , >、>= 后面或子查询用作表达式时,这是不允许的。

我不知道为什么会出现错误。

SELECT
    CASE 
       WHEN LJT.POSTING IN (20, 31, 41) 
            AND LEFT(LJT.VOUCHER, 3) NOT IN ('REC', 'PAY', 'GEN', 'ARA', 'NET','900','BDJ','004') 
          THEN (SELECT TOP (1) dbo.CUSTTRANS.INVOICE 
                FROM dbo.CUSTTRANS WITH (nolock) 
                WHERE CUSTTRANS.VOUCHER = LJT.voucher 
                  AND CUSTTRANS.DATAAREAID = LJT.DATAAREAID 
                  AND CUSTTRANS.TRANSDATE = LJT.TRANSDATE 
                UNION
                SELECT TOP (1) dbo.VENDTRANS.VOUCHER 
                FROM dbo.VENDTRANS WITH (nolock) 
                WHERE VENDTRANS.VOUCHER = LJT.voucher 
                  AND VENDTRANS.DATAAREAID = LJT.DATAAREAID 
                  AND VENDTRANS.TRANSDATE = LJT.TRANSDATE)
          ELSE LJT.Voucher 
    END AS NumberTransaction5
FROM 
    BEANRSQLDAX.ecu_AX2009_sp1_ru8_prd.dbo.LedgerTRANS LJT WITH (NOLOCK) 

此外,还有许多其他子查询与此完全相同,但只有这个出现错误。

有人可以给我一些提示吗?

提前谢谢您。

sql t-sql sql-server-2008-r2
1个回答
0
投票

这是一个建议 - 但有注意事项:

错误消息明确指出您的 case 表达式包含一个返回多行的子查询。这是因为有 2 个子查询并且都能够返回行。使用

UNION
并不能保证最终只返回单个值,因为两个值需要相同才能将它们减少到 1 行(但发票和凭证相同的情况可能非常罕见!)。因此,您需要重新考虑如果这两个子查询都返回值会发生什么。例如:

  • 您是否优先考虑发票而不是优惠券(使用
    coalesce
  • 您是否连接两个值?

下面我建议使用合并,但如果您决定这样做,您可以更改为连接。因此,我建议不要在 case 表达式中使用相关子查询,而是将它们移到单独的 OUTER APPLY 中,如下所示:

SELECT CASE 
        WHEN LJT.POSTING IN (20, 31, 41)
            AND LEFT(LJT.VOUCHER, 3) NOT IN ('REC', 'PAY', 'GEN', 'ARA', 'NET', '900', 'BDJ', '004')
            THEN coalesce(oac.cust_invoice, oav.vend_voucher)
        ELSE LJT.Voucher
        END AS NumberTransaction5
FROM BEANRSQLDAX.ecu_AX2009_sp1_ru8_prd.dbo.LedgerTRANS LJT WITH (NOLOCK)
OUTER APPLY (
    SELECT TOP (1) dbo.CUSTTRANS.INVOICE AS cust_invoice
    FROM dbo.CUSTTRANS WITH (NOLOCK)
    WHERE CUSTTRANS.VOUCHER = LJT.voucher
        AND CUSTTRANS.DATAAREAID = LJT.DATAAREAID
        AND CUSTTRANS.TRANSDATE = LJT.TRANSDATE
        AND LJT.POSTING IN (20, 31, 41)
        AND LEFT(LJT.VOUCHER, 3) NOT IN ('REC', 'PAY', 'GEN', 'ARA', 'NET', '900', 'BDJ', '004')
    ORDER BY CUSTTRANS.TRANSDATE DESC
    ) AS oac
OUTER APPLY (
    SELECT TOP (1) dbo.VENDTRANS.VOUCHER AS vend_voucher
    FROM dbo.VENDTRANS WITH (NOLOCK)
    WHERE VENDTRANS.VOUCHER = LJT.voucher
        AND VENDTRANS.DATAAREAID = LJT.DATAAREAID
        AND VENDTRANS.TRANSDATE = LJT.TRANSDATE
        AND LJT.POSTING IN (20, 31, 41)
        AND LEFT(LJT.VOUCHER, 3) NOT IN ('REC', 'PAY', 'GEN', 'ARA', 'NET', '900', 'BDJ', '004')
    ORDER BY VENDTRANS.TRANSDATE
    ) AS oav

另请注意,使用

TOP
时,您还应该使用
ORDER BY
,否则结果是不确定的 - 但我不知道哪些列有意义,因此我从识别的几列中任意选择。您应该在最终查询中更正此问题。

© www.soinside.com 2019 - 2024. All rights reserved.