如何在SQL Server 2016的CASE WHEN中复用子查询结果做比较
问题解答:SQL Server 2016中CASE语句引用子查询聚合值的写法问题
嘿,我来帮你解决这个SQL问题!首先明确说:SQL Server 2016不支持你尝试的那种写法——你没法直接在CASE的WHEN子句里引用CASE表达式开头那个子查询的Count结果,因为它们属于不同的作用域,子查询的内部聚合值没法被外部的WHEN条件直接捕获,这就是你遇到语法错误的原因。
最优替代方案:用CROSS APPLY预计算计数
这种方式不仅语法合法,还能避免重复执行子查询,性能更优。我们可以通过CROSS APPLY为主表的每一行预先计算出对应的CPD候选人数量,然后在CASE语句里直接引用这个预计算的字段:
SELECT CASE WHEN cpdCalc.CandidateCount > 0 THEN 'Bigger' ELSE 'Equal or Smaller' END AS CountResult FROM -- 这里替换成你的主表名称(对应原语句里的can别名) YourMainTable can CROSS APPLY ( SELECT COUNT(ID) AS CandidateCount FROM CPD_Candidates cpdCan WHERE cpdCan.CandidateID = can.CandidateID AND ( cpdCan.DateEnded >= GETDATE() OR COALESCE(cpdCan.DateEnded, '1900-01-01') = '1900-01-01' ) AND cpdCan.Deleted <> 1 ) cpdCalc
备选方案:直接在WHEN条件中嵌入子查询
如果不想用CROSS APPLY,也可以把整个计数子查询直接放到WHEN的判断条件里,这种写法语法合法,但如果这个CASE逻辑在查询中多次出现,子查询会被重复执行,性能不如上面的方案:
SELECT CASE WHEN ( SELECT COUNT(ID) FROM CPD_Candidates cpdCan WHERE cpdCan.CandidateID = can.CandidateID AND ( cpdCan.DateEnded >= GETDATE() OR COALESCE(cpdCan.DateEnded, '1900-01-01') = '1900-01-01' ) AND cpdCan.Deleted <> 1 ) > 0 THEN 'Bigger' ELSE 'Equal or Smaller' END AS CountResult FROM YourMainTable can
小优化建议
原语句里的COALESCE(cpdCan.DateEnded, '') = N'1-Jan-1900'可以调整得更严谨:因为DateEnded是日期类型,和空字符串比较会触发隐式转换,建议改成COALESCE(cpdCan.DateEnded, '1900-01-01') = '1900-01-01',或者直接写成cpdCan.DateEnded IS NULL OR cpdCan.DateEnded = '1900-01-01',避免不必要的类型转换问题。
内容的提问来源于stack exchange,提问作者user11455272
相关产品推荐
相关产品推荐

