I wonder if there is any wise way to rewrite the following query so that the indexes on columns get used by optimizer?
Have you tries a table valued function?
CREATE FUNCTION select_func1 (
@Key1 int=0,
@Key2 int=0
)
RETURNS TABLE
AS RETURN (
Select key3
From Or_Table
Where (@key1 =0 OR Key1 =@Key1) AND
(@key2 =0 OR Key2 =@Key2)
)
select * from select_func1(1,2)
Yes - careful use of dynamic sql will solve this problem. There are two ways to do it:
If you are a "purist" about stored procs, then compose a custom query string inside a stored proc and execute the string. The specific query then can be dynamically written per execution to include only the relevant criteria.
If you are flexible about the location of this SQL, you can (again CAREFULLY) compose the query string in your application and pass it to the server.
The danger, of course, is around SQL injection. So you have to be very careful how the data is passed from client into the dynamic sql statement.
Really thorough and comprehensive articles from Erland Sommarskog:
SQL Server
is not very good in optimizing the OR
predicates.
Use this:
SELECT key3
FROM or_table
WHERE @key1 = 0
AND @key2 = 0
UNION ALL
SELECT key3
FROM or_table
WHERE @key1 = 0
AND @key2 <> 0
AND key2 = @key2
UNION ALL
SELECT key3
FROM or_table
WHERE @key2 = 0
AND @key1 <> 0
AND key1 = @key1
UNION ALL
SELECT key3
FROM or_table
WHERE @key1 <> 0
AND @key2 <> 0
AND key1 = @key1
AND key2 = @key2
SQL Server
will look to the values of the variables prior to executing the queries and will optimize the redundant queries out.
This means that only one query of four will be actually executed.
MSSQL 2008 has optimization syntax of condition simplification, here it is
Where (@key1 =0 OR Key1 =@Key1) AND
(@key2 =0 OR Key2 =@Key2) option(recompile)
This will optimize usage of constants