I would like to change the WHERE clause of a query based upon the value of an input parameter. I'm guessing this is possible, but it seems that I'm approaching it in the wrong way? 
A simplified version on my SP query:
CREATE PROCEDURE [dbo].[GetMailboxMessagesByStatus]
    @UserId             UNIQUEIDENTIFIER,
    @MessageStatus      INT
AS
BEGIN
    SELECT  * 
    FROM  MailboxMessages m
    WHERE
    CASE @MessageStatus
        WHEN 4 THEN m.SenderId = @UserId    --Sent
        ELSE m.RecipientId = @UserId        --Inbox
    END
END 
GO
                You can specify multiple conditions in a single WHERE clause to, say, retrieve rows based on the values in multiple columns. You can use the AND and OR operators to combine two or more conditions into a compound condition. AND, OR, and a third operator, NOT, are logical operators.
Solution 1. You can use parameters in a WITH clause just like in a traditional statement. The problem in the example is the IN operator which requires a list of values.
You can't use a variable in an IN clause - you need to use dynamic SQL, or use a function (TSQL or CLR) to convert the list of values into a table.
The IN operator allows you to specify multiple values in a WHERE clause. The IN operator is a shorthand for multiple OR conditions.
No need for case or iif constructs:
WHERE @MessageStatus = 4  AND  m.SenderId = @UserId
   OR @MessageStatus <> 4 AND  m.RecipientId = @UserId
EDIT: Be aware on big tables using this construct when the table being queried is quite large. Using 2 seperate queries using a IF statement like Chester Lim suggested might be the better solution. Preventing parameter sniffing might also be a good idea
Use an IF statement.
CREATE PROCEDURE [dbo].[GetMailboxMessagesByStatus]
    @UserId UNIQUEIDENTIFIER ,
    @MessageStatus INT
AS
    BEGIN
        IF ( @MessageStatus = 4 )
            BEGIN
                SELECT  *
                FROM    MailboxMessages
                WHERE   m.SenderId = @UserId;    --Sent
            END;
        ELSE
            BEGIN
                SELECT  *
                FROM    MailboxMessages m
                WHERE   m.RecipientId = @UserId;        --Inbox
            END; 
    END;
GO
EDIT - a much better way provided by LukStorms (since i did not know IIF until i saw his answer)
CREATE PROCEDURE [dbo].[GetMailboxMessagesByStatus]
    @UserId UNIQUEIDENTIFIER ,
    @MessageStatus INT
AS
    BEGIN
        SELECT  *
        FROM    MailboxMessages m
        WHERE IIF (@MessageStatus = 4, m.SenderId, m.RecipientId) = @UserId;    --Sent
    END       
GO
                        You could change that WHERE clause to
WHERE (CASE WHEN @MessageStatus = 4 THEN m.SenderId ELSE m.RecipientId END) = @UserId
Because what you put after the THEN in a CASE should just be a value, not a comparison.
Or use IIF instead of a CASE:
WHERE IIF(@MessageStatus = 4,m.SenderId,m.RecipientId) = @UserId
But the SQL will run more efficient if you use an IF ... ELSE ... and run a different Query based on the @MessageStatus.
Was writing an example for that, but Chester Lim already beat me to it. ;)
(so no need to repeat that approach in this answer) 
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With