在SQL Server WHERE子句条件中优化CASE WHEN语句

Tej*_*eja 3 sql t-sql sql-server case

我正在重写我的sql以降低执行成本,并想知道是否有一种有效的方法来编写WHERE条件中使用的以下CASE WHEN语句:

SELECT l.*,tg.*
FROM  RefTable tg, 
      InputTbl l
WHERE tg.areascheme = l.areascheme
  AND tg.countrycode = l.strareabriefnamel1  
  AND ( CASE WHEN l.strareabriefnamel2 IS NULL THEN '' ELSE tg.areacode END ) = COALESCE( l.strareabriefnamel2,'' )
  AND ( CASE WHEN l.strareabriefnamel3 IS NULL THEN '' ELSE tg.subareaname END ) = COALESCE( l.strareabriefnamel3,'' )
  AND ( CASE WHEN l.strareabriefnamel4 IS NULL THEN '' ELSE tg.postalname END ) = COALESCE( l.strareabriefnamel4,'' )
  option( MAXDOP 0 ); 
Run Code Online (Sandbox Code Playgroud)

执行计划: - 在此输入图像描述

更多细节 :-

InputTable(466K记录)总共有四个参与JOIN逻辑的字段,总共有16个可能的(NULL,NOT NULL)组合.

L1,  L2,  L3,  L4
NULL,NULL,NULL,NULL
NULL,NULL,NULL,NOT NULL
NULL,NULL,NOT NULL, NULL
NULL,NULL,NOT NULL,NOT NULL
NULL,NOT NULL,NULL,NULL
NULL,NOT NULL,NULL, NOT NULL
NULL,NOT NULL, NOT NULL,NULL
NULL,NOT NULL,NOT NULL,NOT NULL
NOT NULL,NULL,NULL,NULL
NOT NULL,NULL,NULL,NOT NULL
NOT NULL,NULL,NOT NULL,NULL
NOT NULL,NULL,NOT NULL,NOT NULL
NOT NULL,NOT NULL,NULL,NULL
NOT NULL,NOT NULL,NULL,NOT NULL
NOT NULL,NOT NULL,NOT NULL,NULL
NOT NULL,NOT NULL,NOT NULL,NOT NULL
Run Code Online (Sandbox Code Playgroud)

将与InputTable一起参与JOIN逻辑的RefTable(45k记录)根据上述标准生成结果集,产生约3.51亿行.

我的输入数据目前仅满足两种情况.

输入表: -

NULL,NULL,NULL,NULL - 225776 rows
NOT NULL, NOT NULL, NULL, NULL - 240360 rows
Run Code Online (Sandbox Code Playgroud)

任何输入将不胜感激.谢谢.

Gor*_*off 5

简单规则: 不要FROM子句中使用逗号. 始终使用明确,正确的JOIN语法.

这可能不会改变查询的性能,但它是一种更典型的编写方式.我很确定这个意图是:

SELECT l.*, tg.*
FROM RefTable tg JOIN
     InputTbl l
     ON tg.areascheme = l.areascheme AND tg.countrycode = l.strareabriefnamel1  
WHERE (l.strareabriefnamel2 IS NULL OR tg.areacode = l.strareabriefnamel2) AND
      (l.strareabriefnamel3 IS NULL OR tg.subareaname  = l.strareabriefnamel3) AND
      (l.strareabriefnamel4 IS NULL OR tg.postalname = l.strareabriefnamel4)
  option( MAXDOP 0 ); 
Run Code Online (Sandbox Code Playgroud)

优化此查询的起点是索引.我建议:RefTable(areascheme, countrycode)InputTbl(areascheme, strareabriefnamel1).

  • @clifton_h虽然从ANSI-89标准确实如此,它在ANSI-92标准(25年前)中被替换.逗号分隔的列表仍然存在,但长时间不受欢迎.它是交叉连接的简写.主要原因是错过谓词很容易. (2认同)
  • 最好的原因是,您在使用 OUTER 连接(LEFT 和 RIGHT 连接)时使用一致的语法。在过去的糟糕日子里,有一些符号用于此类语法,例如“WHERE table1.field1 *= table2.field1”之类的代码,但实现很粗略,可读性有限,并且使用此时返回的结果可能会有所不同使用 LEFT/RIGHT 语法的语法 - 因为 JOIN 不在 WHERE 子句中。语法的一致性对我来说已经足够了。 (2认同)