SQL CASE语句未识别非NULL值,异常执行ELSE分支求助
问题原因与解决方案
核心问题
你的CASE语句不符合预期的根源在子查询逻辑错误:
- 原中子查询
(SELECT * FROM schema.Values WHERE Currency = 'USD' ORDER BY ChangedDate DESC LIMIT 1)只返回全表最新的单条USD记录,而不是每个CustomerCode对应的最新USD记录。 - 这就导致只有这个唯一的客户能匹配到B表数据,其他所有客户的
B.Shares都会因为LEFT JOIN匹配失败而变为NULL,最终触发ELSE分支返回Z.Float。
另外还有一个潜在问题:你的GROUP BY仅指定了A.CustomerCode,但SELECT中包含Z.Float这类非聚合列,部分数据库(如MySQL开启ONLY_FULL_GROUP_BY模式时)会直接报错,即使不报错,结果也可能不可预期(如果同一个客户在Floats表有多条记录)。
修正后的查询语句
SELECT A.CustomerCode, CASE WHEN B.Shares IS NOT NULL THEN ROUND(B.Shares/1000000.00, 2) ELSE Z.Float END AS Shares FROM schema.Customers A LEFT JOIN ( SELECT CustomerCode, Shares, ROW_NUMBER() OVER (PARTITION BY CustomerCode ORDER BY ChangedDate DESC) AS rn FROM schema.Values WHERE Currency = 'USD' ) B ON B.CustomerCode = A.CustomerCode AND B.rn = 1 LEFT JOIN schema.Floats Z ON Z.CustomerCode = A.CustomerCode WHERE A.UpdateDate = 'yyyy-mm-dd' GROUP BY A.CustomerCode, Shares -- 若Z.Float每个客户唯一,可改为A.CustomerCode, Z.Float ORDER BY A.CustomerCode ASC;
关键修改说明
- 子查询修复:
- 使用
ROW_NUMBER() OVER (PARTITION BY CustomerCode ORDER BY ChangedDate DESC)给每个客户的USD记录按时间倒序排名,取rn=1的记录,确保每个客户都能拿到自己的最新Shares数据。
- 使用
- GROUP BY调整:
- 显式将SELECT中的非聚合列加入GROUP BY,符合数据库的分组规则,避免潜在的语法错误或结果异常。如果
Z.Float对于每个客户是唯一值,也可以直接写A.CustomerCode, Z.Float。
- 显式将SELECT中的非聚合列加入GROUP BY,符合数据库的分组规则,避免潜在的语法错误或结果异常。如果
内容的提问来源于stack exchange,提问作者oddtimesigs
相关产品推荐
相关产品推荐

