0

I would like to make a select query, I have several parameters but depending on the value I add the parameter to the where clause. I do not want to use dynamic query. For example this is my stored declaration:

EXEC GETProducts @ProductID INT = -1, @ProductName NVARCHAR(100) = NULL, @ProductManufacturerID INT = -1

I want all the products manufactured by ManufacturerID = 3

EXEC GETProducts -1, NULL, 3

I would like a query like this, I know it does no work, I also tried with CASE, but not working.

SELECT * FROM Product
WHERE 
IF(@ProductID > -1)
BEGIN
 ProductID = @ProductID
END
AND
IF(@ProductName <> '')
BEGIN
 ProductName = @ProductName 
END
AND
IF(@ProductManufacturerID > -1)
BEGIN
 ProductManufacturerID = @ProductManufacturerID 
END

Thanks for your help!!!

8
  • Show what you tried with CASE since that will be much closer to a working solution than IF. Commented Jan 21, 2016 at 15:37
  • Also if you can try to show what you start with and what your output and expected output is. Commented Jan 21, 2016 at 15:38
  • A case statement seems reasonable in this situation over the IF statement just because of how messy your code might get Commented Jan 21, 2016 at 15:39
  • 1
    Dynamic Search Conditions in T-SQL by Erland Sommarskog covers a lot of options Commented Jan 21, 2016 at 15:41
  • 1
    @MarkHill IF is completely invalid since it's for program flow, not expression evaluation, and can't be used inside a WHERE clause. Commented Jan 21, 2016 at 15:42

7 Answers 7

3

It sounds like you want a combination of ANDs and ORs instead of CASE or IF:

SELECT * FROM Product
WHERE 
(@ProductID <= -1 OR ProductID = @ProductID)
AND
(@ProductName = '' OR ProductName = @ProductName)
AND
(@ProductManufacturerID <= -1 OR ProductManufacturerID = @ProductManufacturerID)

However I would note that NULL is generally preferred to "magic" numbers and strings for special cases:

SELECT * FROM Product
WHERE 
(@ProductID IS NULL OR ProductID = @ProductID)
AND
(@ProductName IS NULL OR ProductName = @ProductName)
AND
(@ProductManufacturerID IS NULL OR ProductManufacturerID = @ProductManufacturerID)
Sign up to request clarification or add additional context in comments.

2 Comments

Using OR, wouldn't he select cases in which only one of the two considitions meet? Supose that @PruductID is -3 and ProductID is 5. Since the clause (@ProductID <= -1 OR ProductID = @ProductID) evaluates true, it will actually select it.
@BlackAdder Correct. The intent is likely to use any negative number as a "magic number" that would select ALL products (effectively to NOT filter by product ID). I'm guessing in this case but it's a common use case.
0
SELECT * 
FROM Product
WHERE 
    (@ProductID = -1 OR ProductID = @ProductID)
AND (@ProductName = '' OR ProductName = @ProductName)
AND (@ProductManufacturerID = -1 OR ProductManufacturerID = @ProductManufacturerID)

Comments

0

I am guessing a bit here. You probably want to write:

WHERE 
(@ProductID > -1 AND ProductID = @ProductID)
OR
(@ProductName <> '' AND ProductName = @ProductName )
OR
(@ProductManufacturerID > -1 AND ProductManufacturerID = @ProductManufacturerID)

Comments

0

You can make "conditional" WHERE clauses by pairing them with OR clauses. Something like this:

SELECT * FROM Product
WHERE
    (@ProductID <= -1 OR ProductID = @ProductID)
    AND @ProductName = '' OR ProductName = @ProductName)
    -- etc.

That way if the "conditional check" is true than the second half of the OR clause isn't evaluated.

Comments

0

You can change your query to be like below by making the conditions to be composite condition and you don't need a CASE expression. BTW, IF .. ELSE construct works only within a procedural body.

SELECT * FROM Product
WHERE (@ProductID > -1 AND ProductID = @ProductID)
AND (@ProductName <> '' AND ProductName = @ProductName)
AND (@ProductManufacturerID > -1 AND ProductManufacturerID = @ProductManufacturerID)

Comments

0

You can translate the conditionals into requirements inside the WHERE clause.

IF(@ProductID > -1)
BEGIN
    ProductID = @ProductID
END

is equivalent to:

ProductID > -1 AND ProductID = @ProductID

,

IF(@ProductName <> '')
BEGIN
    ProductName = @ProductName 
END

is equivalent to:

ProductName <> '' AND ProductName = @ProductName

,

IF(@ProductManufacturerID > -1)
BEGIN
    ProductManufacturerID = @ProductManufacturerID 
END

is equivalent to:

ProductManufacturerID > -1 AND ProductManufacturerID = @ProductManufacturerID 

So your final Query will be:

SELECT * FROM Product WHERE 
ProductID > -1 AND
ProductID = @ProductID AND
ProductName <> '' AND
ProductName = @ProductName AND
ProductManufacturerID > -1 AND
ProductManufacturerID = @ProductManufacturerID 

2 Comments

Your "equivalents" are not correct - e.g. if @ProductID is less than -1 then there would be NO filter on ProductID. Your equivalent would remove ALL records if @ProductID is less than -1.
I misunderstood what @user2112420 wanted to achieve. To me, it looked like he wanted first to check if a product has ID > -1 and then check if it corresponds to the ID in the variable.
0

The when your parameter is intended to affect the select query the case will evaluate to 1 therefore making it part of the select statement, if not it will be 0 therefore it will not count because 0=1 will evaluate to false.

SELECT * FROM Product
WHERE 
(CASE 
     WHEN @ProductId > -1 AND ProductId = @ProductId THEN 1 
     ELSE 0
 END) = 1
AND 
(CASE 
     WHEN @ProductName <> '' AND ProductName = @ProductName THEN 1 
     ELSE 0
END) = 1
AND 
(CASE
     WHEN @ProductManufacturerID > -1 AND ProductManufacturerID = @ProductManufacturerID THEN 1 
END);

2 Comments

You miss the part when comparing the @parameter with the row value
@JuanCarlosOropeza Edited my answer, it should be fine now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.