问题
I am rewriting my sql to reduce the cost of execution and wondering if there is an efficient way to write the below CASE WHEN statements used in WHERE condition:
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 );
Execution Plan :-
More Details :-
InputTable( 466K records ) has total four fields which participate in JOIN logic and there are total 16 possible ( NULL,NOT NULL )combinations.
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
RefTable( 45k records ) which will participate in the JOIN logic with InputTable is generating the resultset based on the above criteria is producing around 351 million rows.
My input data is currently meeting only two scenarios.
InputTable :-
NULL,NULL,NULL,NULL - 225776 rows
NOT NULL, NOT NULL, NULL, NULL - 240360 rows
Any inputs would be appreciated. Thanks.
回答1:
Simple rule: Never use commas in the FROM clause. Always use explicit, proper JOIN syntax.
This probably doesn't change the performance of the query, but it is a much more typical way to write it. I'm pretty sure the intention is:
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 );
The place to start with optimizing this query is with indexes. I would suggest: RefTable(areascheme, countrycode) and InputTbl(areascheme, strareabriefnamel1).
来源:https://stackoverflow.com/questions/41109254/optimizing-case-when-statement-in-sql-server-where-clause-condition