SSMS(SQL)中CASE WHEN语句未生效,始终执行ELSE 0问题咨询
这种情况我碰到过好几次,大概率是下面几个常见问题导致的,一个个排查应该就能解决:
数据类型不匹配或存在隐形字符
虽然你看到两个值都是55,但很可能它们的数据类型不一样(比如一个是INT,另一个是VARCHAR),或者字符串类型的字段里藏了空格、换行这类不可见字符。SQL里不同类型做相等判断时,隐式转换可能会出问题;如果是带隐形字符的字符串,'55'和'55 '看起来一样,但实际不相等。
验证方法:- 用
DATA_TYPE查看字段类型:SELECT DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='你的表名' AND COLUMN_NAME IN ('ORDER_NUMBER', 'Calc_ORDER_NUMBER_LAG') - 检查字符串长度:
SELECT ORDER_NUMBER, Calc_ORDER_NUMBER_LAG, LEN(Calc_ORDER_NUMBER_LAG) FROM 你的表名,如果长度大于2,说明有隐形字符,可以用LTRIM(RTRIM(Calc_ORDER_NUMBER_LAG))去除后再比较。
- 用
NULL值的干扰
SQL里NULL和任何值做相等判断的结果都是UNKNOWN,而CASE WHEN只会执行条件为TRUE的分支,UNKNOWN会直接跳到ELSE。如果ORDER_NUMBER或Calc_ORDER_NUMBER_LAG有NULL值,哪怕看起来是55,实际判断也不成立。
解决方法:在CASE里先处理NULL情况,比如:CASE WHEN ORDER_NUMBER IS NOT NULL AND Calc_ORDER_NUMBER_LAG IS NOT NULL AND ORDER_NUMBER = Calc_ORDER_NUMBER_LAG THEN 2 ELSE 0 END AS Calc_Qty_ChangedLAG函数的窗口范围错误
你用LAG(ORDER_NUMBER)计算Calc_ORDER_NUMBER_LAG的时候,有没有正确设置PARTITION BY和ORDER BY?如果分区字段不对,或者排序逻辑错了,LAG取到的可能不是你预期的上一行值——比如你以为是按客户分区取上一个订单,但实际没加PARTITION BY CustomerID,导致取到了其他客户的订单号,看起来某一行是55,但实际LAG的值是其他行的。
验证方法:单独查询ORDER_NUMBER和Calc_ORDER_NUMBER_LAG两列,逐行核对对应关系,确认每一行的LAG值确实是你期望的上一行同组的订单号。CASE WHEN的条件顺序问题
有没有在WHEN ORDER_NUMBER = Calc_ORDER_NUMBER_LAG这个分支前面,还有其他WHEN条件已经被满足了?CASE WHEN是从上到下匹配第一个满足条件的分支,如果前面有一个条件(比如WHEN QTY <> LAG(QTY) THEN 1)已经符合当前行的情况,就会返回1,根本不会走到后面的分支。
解决方法:调整CASE WHEN的条件顺序,把你想要优先匹配的分支放在前面。
举个修正后的示例代码,结合了上面的排查点:
SELECT ORDER_NUMBER, LAG(ORDER_NUMBER) OVER (PARTITION BY CustomerID ORDER BY OrderDate) AS Calc_ORDER_NUMBER_LAG, CASE WHEN ORDER_NUMBER IS NULL OR Calc_ORDER_NUMBER_LAG IS NULL THEN 0 WHEN CAST(ORDER_NUMBER AS VARCHAR(10)) = LTRIM(RTRIM(CAST(Calc_ORDER_NUMBER_LAG AS VARCHAR(10)))) THEN 2 ELSE 0 END AS Calc_Qty_Changed FROM YourOrdersTable
内容的提问来源于stack exchange,提问作者mitchmitch24

