17

I have a query in sql 2008 where a use can select multiple optional parameters like these:

@DateFrom
@DateTo
@UserType
@Customer
@User

What's the best / most performant approach to filtering based on all of these options?

  • separate select statements for different cases
  • using coalesce
  • etc.
KyleMit
  • 30,350
  • 66
  • 462
  • 664
vicky
  • 241
  • 1
  • 3
  • 12
  • 2
    possible duplicate of [How can I use optional parameters in a T-SQL stored procedure?](http://stackoverflow.com/questions/3415582/how-can-i-use-optional-parameters-in-a-t-sql-stored-procedure) – Conrad Frix Mar 04 '14 at 18:38

3 Answers3

31

You can avoid using multiple IF ELSE condition and dynamic query by using this approach.

SELECT * FROM TBL
WHERE (@Name IS NULL OR Name = @Name) 
AND (@Age IS NULL OR Age = @Age)
Shantanu Gupta
  • 20,688
  • 54
  • 182
  • 286
15

you can write you WHERE Clause something like this.....

This is a quick fix but a bad approach,,,,,

SELECT ......
FROM TABLE
WHERE 
     (@UserType IS NULL OR UserType = @UserType)
AND
    (@Customer IS NULL OR Customer = @Customer)
AND
    (@User IS NULL OR User = @User)
AND
    (<Similarly Other Conditions>)

The proper way of writing a query like this should be using dynamic SQL with the use of sp_executesql

-- Optional Variables

Declare @UserType   VARCHAR(10) = NULL
    ,   @Customer   INT = 123
    ,   @User       INT = 123
    ,   @Sql        NVARCHAR(MAX);


-- Build SQL Dynamically 

 SET @Sql = N'  SELECT *
                FROM TABLE_Name
                WHERE 1 = 1 '
          + CASE WHEN @UserType IS NOT NULL THEN
            N' AND UserType = @UserType ' ELSE N' ' END
          +  CASE WHEN @Customer IS NOT NULL THEN
            N' AND Customer = @Customer ' ELSE N' ' END
          +  CASE WHEN @User IS NOT NULL THEN
            N' AND User = @User ' ELSE N' ' END

-- Finally Execute SQL 

 Exec sp_executesql @Sql
                , N'@UserType VARCHAR(10) , @Customer INT , @User INT'
                , @UserType
                , @Customer
                , @User;
M.Ali
  • 67,945
  • 13
  • 101
  • 127
3

You can use a dynamic query

SELECT @sql=
'SELECT DISTINCT [Test_Id], [Test].[Test_Name], [Test].[Test_Date]
    FROM [Test]
    WHERE (1 = 1)'

IF @start IS NOT NULL
    SELECT @sql = @sql + ' AND ([Test].[Test_Date] >= @start)'
IF @end IS NOT NULL
    SELECT @sql = @sql + ' AND ([Test].[Test_Date] <= @end)'

SELECT @paramlist = '@start datetime, 
    @end datetime'

EXEC sp_executesql @sql, @paramlist,
    @start, 
    @end

You can also use different queries but if you have more than 2 parameters it's very annoying code

IF(@start IS NULL)
    IF(@end IS NULL)
        SELECT ...
    ELSE
        SELECT ...
ELSE
    IF(@end IS NULL)
        SELECT ...
    ELSE
         SELECT ...
meziantou
  • 20,589
  • 7
  • 64
  • 83
  • Thanks for your prompt suggestion..actually your main select statement is using only one table i.e 'Test', but in my case I have to select values from 4-5 different tables using joins etc..so I think dynamic sql might be a bit tedious :). anyway I am trying on it.. Thanks – vicky Mar 04 '14 at 18:31
  • Why can't you use JOIN with dynamic queries: `FROM Test JOIN ...` – meziantou Mar 04 '14 at 18:35
  • I know this question is labled with sql-server but the sp_executesql doesn't work in mysql. – aderchox Aug 11 '20 at 00:49