You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CASE表达式无返回行时如何显示指定值?SQL查询求助

我来帮你搞定这个问题!你的核心需求很明确:不管R5TRANSLINES里有没有符合条件的行,都得返回一行结果,ORG固定是'198'(或者你更新代码里的'ESREQ1'),SumTotal要么是计算值,要么是NULL/指定默认值。之前的方法没用,是因为当原查询没有匹配行时,整个SELECT根本没有数据源,自然不会输出任何内容——ISNULL这类函数只对已有行的字段生效,没有行的话它们根本没机会发挥作用。

问题根源分析

原代码和你更新后的代码,都是直接从R5TRANSLINES取数计算。如果这个表没有符合条件的记录,整个查询就没有“基础行”,哪怕你用了窗口函数SUM() OVER(),也没法凭空生成一行结果。

解决方案:强制生成一行基础数据

我们可以先构造一个固定的单一行数据源(比如用VALUES (1)生成一个临时行),然后用LEFT JOIN关联你的计算查询。这样哪怕计算查询没有结果,固定的那一行也会保留,再用ISNULL/COALESCE给SumTotal设置默认值就可以了。

方案1:无匹配时返回NULL作为SumTotal

DECLARE @startdate VARCHAR(30);
DECLARE @enddate VARCHAR(30);
DECLARE @count INT;

SET @startdate = '2017-12-01';
SET @enddate = '2018-01-01';

-- 先统计符合条件的行数,和你原逻辑一致
SELECT @count = COUNT(*) 
FROM R5TRANSLINES 
WHERE TRL_TYPE = 'STTK' 
  AND TRL_TRANS IN (
      SELECT TRA_CODE 
      FROM R5TRANSACTIONS 
      WHERE TRA_FROMCODE IN ('198') 
        AND TRA_STATUS IN ('A') 
        AND TRA_DATE BETWEEN @startdate AND @enddate
  );

-- 用固定行LEFT JOIN计算结果,确保总有输出
SELECT 
    '198' AS ORG,
    calc.SumTotal
FROM (VALUES (1)) AS dummy(id) -- 这里生成一个固定的单一行
LEFT JOIN (
    -- 这里是你原有的计算逻辑,只返回SumTotal字段
    SELECT 
        (SUM(CASE 
            WHEN (TRL_ORIGQTY = 0 AND TRL_ORIGQTY > 0) THEN 0 
            WHEN ((TRL_ORIGQTY - TRL_QTY) = 0 AND TRL_ORIGQTY = 0) THEN 100 
            WHEN ((TRL_ORIGQTY - TRL_QTY) > TRL_ORIGQTY) THEN ((TRL_ORIGQTY / (TRL_ORIGQTY - TRL_QTY)) * 100) 
            ELSE (((TRL_ORIGQTY - TRL_QTY) / TRL_ORIGQTY) * 100) 
        END) OVER () / @count) AS SumTotal
    FROM R5TRANSLINES 
    WHERE TRL_TYPE = 'STTK' 
      AND TRL_TRANS IN (
          SELECT TRA_CODE 
          FROM R5TRANSACTIONS 
          WHERE TRA_FROMCODE IN ('198') 
            AND TRA_STATUS IN ('A') 
            AND TRA_DATE BETWEEN @startdate AND @enddate
      )
) AS calc ON 1=1; -- 无条件关联,确保固定行能拿到计算结果(如果有的话)

方案2:无匹配时返回指定默认值(比如0或者'00001')

只需要把上面的calc.SumTotal改成ISNULL(calc.SumTotal, 0)就行,如果要返回字符串'00001',注意类型匹配(比如把0换成'00001'):

DECLARE @startdate VARCHAR(30);
DECLARE @enddate VARCHAR(30);
DECLARE @count INT;

SET @startdate = '2017-12-01';
SET @enddate = '2018-01-01';

SELECT @count = COUNT(*) 
FROM R5TRANSLINES 
WHERE TRL_TYPE = 'STTK' 
  AND TRL_TRANS IN (
      SELECT TRA_CODE 
      FROM R5TRANSACTIONS 
      WHERE TRA_FROMCODE IN ('198') 
        AND TRA_STATUS IN ('A') 
        AND TRA_DATE BETWEEN @startdate AND @enddate
  );

SELECT 
    '198' AS ORG,
    -- 无匹配时返回0,你可以改成'00001'等指定值
    ISNULL(calc.SumTotal, 0) AS SumTotal
FROM (VALUES (1)) AS dummy(id)
LEFT JOIN (
    SELECT 
        (SUM(CASE 
            WHEN (TRL_ORIGQTY = 0 AND TRL_ORIGQTY > 0) THEN 0 
            WHEN ((TRL_ORIGQTY - TRL_QTY) = 0 AND TRL_ORIGQTY = 0) THEN 100 
            WHEN ((TRL_ORIGQTY - TRL_QTY) > TRL_ORIGQTY) THEN ((TRL_ORIGQTY / (TRL_ORIGQTY - TRL_QTY)) * 100) 
            ELSE (((TRL_ORIGQTY - TRL_QTY) / TRL_ORIGQTY) * 100) 
        END) OVER () / @count) AS SumTotal
    FROM R5TRANSLINES 
    WHERE TRL_TYPE = 'STTK' 
      AND TRL_TRANS IN (
          SELECT TRA_CODE 
          FROM R5TRANSACTIONS 
          WHERE TRA_FROMCODE IN ('198') 
            AND TRA_STATUS IN ('A') 
            AND TRA_DATE BETWEEN @startdate AND @enddate
      )
) AS calc ON 1=1;

适配你更新后的代码

如果你需要用更新后的逻辑(ORG为'ESREQ1',条件包含UPPER(TRA_DESC) like '%AUDITESREQ1%'),只需要把代码里的'198'替换成'ESREQ1',并把WHERE子句里的条件换成你更新后的版本就行,核心逻辑完全一致。

为什么之前的ISNULL/NOT EXISTS没用?

  • ISNULL是对已有行的字段做判断,如果查询没有返回行,它根本没有处理对象;
  • NOT EXISTS如果只是作为查询条件,同样不会生成新行——除非你用UNION ALL把NOT EXISTS的判断结果和原查询合并,但这种方式不如LEFT JOIN固定行简洁。

内容的提问来源于stack exchange,提问作者Piston

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:23:53