Reputation: 344
I have a stored procedure to return results filtered by some parameter (all parameters are optional).
Sometimes I want to get results where condition1 AND condition2 are true, and sometimes when only one of conditions is true.
SELECT
*
FROM
ProductAndServices
WHERE
Title = ISNULL(@Title,Title) @AndOR
CreatedBy = ISNULL(@CreatedBy,CreatedBy)
Upvotes: 1
Views: 492
Reputation: 3905
You could introduce a variable/parameter that specifies if you want to use AND or OR logic with your fields and incorporate that parameter in your WHERE-clause as well.
Something like this, for example:
-- Declared a variable here, but might be a stored procedure parameter as well
DECLARE @And BIT = 1 -- When 0, WHERE uses OR; when 1, WHERE uses AND
SELECT
*
FROM
ProductAndServices
WHERE
(@And = 0 AND (Title = ISNULL(@Title, Title) OR CreatedBy = ISNULL(@CreatedBy, CreatedBy))) OR
(@And = 1 AND (Title = ISNULL(@Title, Title) AND CreatedBy = ISNULL(@CreatedBy, CreatedBy)))
OPTION (RECOMPILE)
Furthermore, I would avoid using functions like ISNULL
in the WHERE-clause, because it might prevent the query optimizer to use indexes.
So instead of this:
Title = ISNULL(@Title, Title)
CreatedBy = ISNULL(@CreatedBy, CreatedBy)
I would use:
(@Title IS NULL OR Title = @Title)
(@CreatedBy IS NULL OR CreatedBy = @CreatedBy)
With this, the query would become:
SELECT
*
FROM
ProductAndServices
WHERE
(@And = 0 AND ((@Title IS NULL OR Title = @Title) OR (@CreatedBy IS NULL OR CreatedBy = @CreatedBy))) OR
(@And = 1 AND ((@Title IS NULL OR Title = @Title) AND (@CreatedBy IS NULL OR CreatedBy = @CreatedBy)))
OPTION (RECOMPILE)
So this latter query is longer and not as readable as the former query, but it should perform better. I think. I have not tested it. You might want to benchmark it with several datasets (and check out the corresponding execution plans) to be sure.
Edit:
Based on a tip by Marc Guillot, I added OPTION (RECOMPILE)
to the query. You could check out the Query Hints documentation in Microsoft Docs for more info about it.
I also found the article Improving query performance with OPTION (RECOMPILE), Constant Folding and avoiding Parameter Sniffing issues by Robin Lester just now. Haven't read it completely yet, but after scanning it quickly, it looks like a good read to me.
Upvotes: 2
Reputation: 144
Write as SQL Statement like below
DECLARE @str VARCHAR(max)=N'SELECT *
FROM ProductAndServices
WHERE Title='+ CASE WHEN @Tittle IS NULL THEN 'Title' ELSE '''' + @Tittle + '''' END
+ ' AND CreatedBy='+ CASE WHEN @CreatedBy IS NULL THEN 'CreatedBy' ELSE '''' + @CreatedBy + '''' END
PRINT @str;
Upvotes: 0
Reputation: 1369
The following query should do what you want,
SELECT *
FROM ProductAndServices
WHERE
(@Title IS NULL OR Title = @Title) AND
(@CreatedBy IS NULL OR CreatedBy = @CreatedBy)
Upvotes: 0
Reputation: 43636
You can try building dynamic T-SQL statement in your routine. It is a little more difficult to write and debug, but it will lead to more simple T-SQL statements being execute and from there - possibility for better performance. Here is an example:
DECLARE @Tittle VARCHAR(12)
,@CreatedBy VARCHAR(12)
,@AndOR VARCHAR(12)
SELECT @Tittle = 'Here comes the sun'
,@CreatedBy = 'Beatles'
,@AndOR = 'AND';
SELECT @Tittle = ISNULL(@Tittle, '')
,@CreatedBy = ISNULL(@CreatedBy, '')
,@AndOR = ISNULL(@AndOR, 'AND');
DECLARE @DynammicTSQLStatement NVARCHAR(MAX);
SET @DynammicTSQLStatement =N'
SELECT
*
FROM
ProductAndServices
WHERE ' + CASE WHEN @Tittle = '' THEN '' ELSE 'Title = ''' + @Tittle + '''' END
+ CASE WHEN @Tittle <> '' AND @CreatedBy <> '' THEN ' ' + @AndOR + ' CreatedBy = ''' + @CreatedBy + '''' ELSE '' END;
SELECT @DynammicTSQLStatement
EXEC sp_executesql @DynammicTSQLStatement;
Upvotes: 1
Reputation: 3833
Use if
condition for your case:
GO
if (@Condtion)
Begin
SELECT * FROM ProductAndServices
WHERE
Title = ISNULL(@Title,Title) And
CreatedBy = ISNULL(@CreatedBy,CreatedBy)
End
Else
Begin
SELECT * FROM ProductAndServices
WHERE
Title = ISNULL(@Title,Title) OR
CreatedBy = ISNULL(@CreatedBy,CreatedBy)
End
I am sure you know your sometimes
when you want to use AND
and when to use OR
.
Upvotes: 0