SQL Server 2008 - Conditional Query

前端 未结 6 1489
说谎
说谎 2020-12-10 19:09

SQL is not one of my strong suits. I have a SQL Server 2008 database. This database has a stored procedure that takes in eight int parameters. For the sake of keeping this q

相关标签:
6条回答
  • 2020-12-10 19:37

    best source for dynamic search conditions:

    Dynamic Search Conditions in T-SQL by Erland Sommarskog

    there are a lot of subtle implications on how you do this as to if an index can be used or not. If you are on the proper release of SQL Server 2008 you can just add OPTION (RECOMPILE) to the query and the local variable's value at run time is used for the optimizations.

    Consider this, OPTION (RECOMPILE) will take this code (where no index can be used with this mess of ORs):

    WHERE
        (@search1 IS NULL or Column1=@Search1)
        AND (@search2 IS NULL or Column2=@Search2)
        AND (@search3 IS NULL or Column3=@Search3)
    

    and optimize it at run time to be (provided that only @Search2 was passed in with a value):

    WHERE
        Column2=@Search2
    

    and an index can be used (if you have one defined on Column2)

    0 讨论(0)
  • 2020-12-10 19:42

    .... Where field=case @isActive WHEN -1 THEN field ELSE @isActive END ....

    0 讨论(0)
  • 2020-12-10 19:47

    Rather than using -1 to signify that you don't know or don't care, how about just using Null for that? Pretty much what it was made for. Then you could switch to a Bit rather than an Int.

    Also, I'm sure TomTom will disagree, but I think using a CASE statement is the way to go for this stuff.

    Your mileage may vary, but it seems that the query engine handles it a lot better than wrapping things in IsNull or having multiple OR statements, which can get rather messy as you start adding other conditions.

    No matter which way you go, the execution plan is going to suffer a little bit depending on what you're passing in, but it shouldn't be TOO horrible.

    The extra benefit of going with CASE statements is that you can add a bit of complexity without much extra code (versus going with a bunch of OR statements). Also, the first condition to match your criteria can prevent the extra evaluations, which isn't always the case when dealing with OR's...

    So, for 8 optional parameters with -1 as the value use to ignore the search, what you end up with is something along the lines of:

    WHERE
            @Search1 = CASE WHEN @Search1 = -1 THEN @Search1 ELSE @Column1 END
        AND @Search2 = CASE WHEN @Search2 = -1 THEN @Search1 ELSE @Column2 END
        AND @Search3 = CASE WHEN @Search3 = -1 THEN @Search1 ELSE @Column3 END
        AND @Search4 = CASE WHEN @Search4 = -1 THEN @Search1 ELSE @Column4 END
        AND @Search5 = CASE WHEN @Search5 = -1 THEN @Search1 ELSE @Column5 END
        AND @Search6 = CASE WHEN @Search6 = -1 THEN @Search1 ELSE @Column6 END
        AND @Search7 = CASE WHEN @Search7 = -1 THEN @Search1 ELSE @Column7 END
        AND @Search8 = CASE WHEN @Search8 = -1 THEN @Search1 ELSE @Column8 END
    

    NOTE: As KM pointed out, the NULL method falls short if the columns you're working will can potentially have NULL values, since NULL=NULL won't evaluate properly. So, for fun, I changed my answer back to what the original poster requested, which is to use their own identifier for skipping the search.

    0 讨论(0)
  • 2020-12-10 19:49

    The pattern (column = @param OR @param IS NULL) will give you optional parameters. You can use NULLIF to neutralize your -1. Even better would be to allow null parameters, instead of using a magic number.

    WHERE
       (Customer.IsActive = NULLIF(@isActive, -1) OR NULLIF(@isActive, -1) IS NULL)
    
    0 讨论(0)
  • 2020-12-10 19:52
    WHERE coalesce(active,1) = (CASE 
                                  WHEN @isActive = -1 THEN coalesce(active,1)
                                  ELSE @isActive
                                END)
    
    0 讨论(0)
  • 2020-12-10 19:55

    There is NOT an elegant way - all ways suck.

    WHERE @isActive == -1 OR isActive = @isActive

    is basically the only way - but even then you please make sure that the query plan is reevaluated every time, otherwise most queries will use the wrong query plan.

    THis is a classical case where stored procedures are bad. Querying should IMHO not be done using stored procedures at all since modern times - which started about 15 years ago when someone was smart enough to write the first ORM.

    0 讨论(0)
提交回复
热议问题