tags:

views:

57

answers:

3

I want to create a stored procedure. If the parameter is -1 then there should not be a where clause on that column else there should be a WHERE clause. What's the best way to do it without a lot of IF branching?

I checked the archive. There are a few similar questions but not exactly the same.

CREATE PROCEDURE report
(
  @site int,
  @promo int,
  @type int
)
AS
SET NOCOUNT ON

-- I want to avoid this:
IF @site = -1 AND @promo = -1 and @type = -1
BEGIN
  SELECT * from table
END
IF @site > -1 AND @promo = -1 and @type = -1
BEGIN
  SELECT * from table WHERE site = @site;
END
... -- other cases


ELSE  -- all parameters are > -1
BEGIN
  SELECT * from table 
  WHERE site = @site AND promo = @promo AND type = @type
END
+3  A: 

This works in many cases, (despite what the comments will say without trying it) because the optimiser will ignore the ISNULL bit. Only works for non-null columns

SELECT @site = NULLIF(@site, -1) ...

SELECT * from table  
  WHERE site = ISNULL(@site, site) ..

Otherwise, conditional WHERE which is usually bad because OR can not be optimised

SELECT * from table  
  WHERE (@site = -1 OR site = @site) AND  (...

Or separate stored procedures (don't think you want that either)

Or use sp_executesql (avoids dynamic SQL)

gbn
+1 for the NULLIF/ISNULL trick, and for being quicker on the draw with a better answer.
meklarian
I implemented the first solution. It took 4 seconds to run. The second solution with the same parameters took 2:40 minutes. Table has 30 millions rows.
Yada
@Yada: I have another convert! People assume it won't scale too
gbn
thanks for this gem. I'll keep this in my sql snippet arsenal.
Yada
+1  A: 

How about:

SELECT * FROM table WHERE
  ((site = @site) OR (@site = -1)) AND
  ((promo = @promo) OR (@promo = -1)) AND
  ((type = @type) OR (@type = -1))

One caveat, though, you may find that SQL is not very intelligent in optimizing this sort of query.

meklarian
+1  A: 

why fight against the obvious, simplest solution?

seriously, the branching solution make the intent clear, and can easily be understood by others.

Steven A. Lowe
Works better on SQL Server 2005 though with statement level recompilation
gbn
For each column there are 2 choices. so 2^3 = 8 branching.
Yada