Using IF/THEN or CASE within a WHERE clause in SQL
I have been assigned the task of updating the EEO survey and reporting for a mid sized company. I am working on a stored procedure to populate a report from. All is good but for a syntax problem. One of the requirements is to dynamically allow the user to filter the results by the EEO Job Group Number. When the report page loads, it populates the table with all Job Groups Combined. I have placed a DropDownList on the page that allows the user to choose one of the 10 EEO Job Groups or by default, All Job Groups Combined (no filtering). The DDL executes postback and populates a parameter; @intEeoJobGroupID. There is not actually a 0 ID value in the table, just in the DDL. I want the (usp) query to use one set of WHERE statements if the passed parameter @intEeoJobGroupID = 0, and another if @intEeoJobGroupID <> 0. (Effectively adding another AND statement if the parameter <> 0)
I want to return the count of how many EEO reco开发者_StackOverflow社区rds meet the requirements of the query. I have tried IF/THEN, and CASE, in many different formats, and can not seem get the syntax right. In the example below I get the message "Incorrect Syntax near the first = in the THEN statement, as well as the keyword ELSE.
Any hints?
DECLARE @intEeoJobGroupID INT
SELECT
COUNT (E.intEeoID)
FROM
dbo.NewEEO AS E
WHERE
CASE WHEN @intEeoJobGroupID = 0
THEN
E.intGenderID = 1
AND E.intRaceID = 2
ELSE
E.intGenderID = 1
AND E.intRaceID = 2
AND E.intEeoJobGroupID = @intEeoJobGroupID
You're making it way too complicated:
WHERE E.intGenderID = 1
AND E.intRaceID = 2
AND (E.intEeoJobGroupID = @intEeoJobGroupID OR @intEeoJobGroupID = 0)
As someone else already mentioned, your existing syntax was missing an "END", but it still won't work with that added. To get this right in the future, one thing you can try to do is remember that CASE expressions in SQL are just that: expressions. They are not statements, as you might be used to with if statements in c# code. You don't use CASE for flow control, to define blocks as you were trying to do.
Don't try to return a boolean
from a CASE statement. Instead return some value that is then checked outside the CASE statement (and so then resulting in a boolean).
CASE WHEN @mode = 1 THEN CASE WHEN <Condition1> THEN 1 ELSE 0 END
WHEN @mode = 2 THEN CASE WHEN <Condition2> THEN 1 ELSE 0 END
END
=
1
Note: This will create Awful execution/explain plans and totally nerf performance. You are better using real IF blocks and real queries, or possibly unions...
IF @mode = 1
SELECT foo FROM bar WHERE <Condition1>
ELSE IF @mode = 2
SELECT foo FROM bar WHERE <Condition2>
Or...
SELECT foo FROM bar WHERE <condition1> AND @mode = 1
UNION ALL
SELECT foo FROM bar WHERE <condition2> AND @mode = 2
In order to prevent massive duplication of code, you may find that encapsulating the bulk of the query in a VIEW is helpful.
You can't make a comparison the result of a case condition. If you're using case
in a where
clause, it needs to be on one side of the operator:
CASE @case_value
WHEN 0 THEN
some_column
ELSE
some_other_column
END = @some_value
However, if you try to make your actual condition fit this rule, you'll end up not using the case
statement at all, as @Joel point out.
You have to add
end
in the end of case.
精彩评论