Reputation: 8208
I have table in MS SQL 2008 which has a column called Status
. It can have "A" or "I" or "P" as values. I have a stored procedure which takes @Status
as a parameter. If the parameter is null
, I need to retrieve all the records where the status is either A or I or P (basically ignoring the Status field). If the paramenter is only A (for example), I need to get only records which have A as the status. How do I get this done in a single SELECT statement without IF.. ELSE
?
-- This is just a snippet of a larger query.
-- Can the following be done without IF ELSE?
IF @Status = NULL
BEGIN
SELECT * FROM Person
END
ELSE SELECT * FROM Person WHERE Status = @Status
Edit: My goal is not to duplicate the same logic twice. The select statement has a bunch of joins and stuff, and I don't want to repeat it again in the else condition.
Edit #2: My bad - I checked the table again and it does contain records with NULL
status, which I don't want. Here's the table -
Id Status
--------------
1 A
2 I
3 P
4 NULL
If @Status
is "-1" (I'll default the parameter to -1), I want 1, 2, 3
records. How do I write the query?
Upvotes: 1
Views: 4179
Reputation: 1564
This should do it:
select * from Person
where (@Status is not null and Status = @Status) or
(@Status is null and Status in ('A', 'I', 'P'))
Upvotes: 0
Reputation: 384
declare @status CHAR(1)
set @status = 'A'
select * from Person where (@status IS null) or (@status = status)
When @status = NULL, this query returns all records.
Upvotes: 0
Reputation:
A third option:
SELECT * FROM dbo.Person WHERE Status = COALESCE(@Status, Status);
Or you might prefer ISNULL:
SELECT * FROM dbo.Person WHERE Status = ISNULL(@Status, Status);
And just for completeness, while the selectivity here is highly unlikely to justify it, you may find that the plans for @Status IS NULL and @Status IS NOT NULL vary widely enough that caching a plan with one or the other can lead to poor performance in the opposite case. One way to deal with this is dynamic SQL. So again, with the disclaimer that this is likely a good option in your case, it is a commonly used alternative to these plan-pinning COALESCE/ISNULL/OR options.
DECLARE @sql NVARCHAR(MAX);
SELECT @sql = N'SELECT * FROM dbo.Person' +
COALESCE(N' WHERE Status = ''' + CONVERT(VARCHAR(12), @Status) + '''', '');
PRINT @sql;
--EXEC sp_executesql @sql;
And of course you know you shouldn't be using SELECT * in production code, right?
Upvotes: 1
Reputation: 838186
You can do it using OR:
SELECT * FROM Person WHERE Status = @Status OR @Status IS NULL
Or UNION ALL:
SELECT * FROM Person WHERE Status = @Status
UNION ALL
SELECT * FROM Person WHERE @Status IS NULL
Upvotes: 1