Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Can I use a CASE statement to switch operators in a TSQL WHERE clause?

I have a complex stored proc, part of which generates dynamic SQL to pivot data in various ways based on a number of factors. For the purposes of this question, I’ll illustrate a simplified example.

One of the parameters passed in is a country, and the data for the pivot is then filtered to that country. However, now requirements have changed, and either a country or a continent may be passed in. What I’d like to do, then, is to have a WHERE clause which uses a CASE statement to either use the = operator or an IN clause, depending on the parameter passed.

Simplified database structure:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

CREATE TABLE Countries
(Country VARCHAR(100),
Continent VARCHAR(20)
)
GO
INSERT INTO  Countries
VALUES ('UK','Europe'),('France','Europe'),('Portugal','Europe'),
('USA','North America'),('Canada','North America'),
('Brazil','South America'),('Peru','South America')
GO

CREATE TABLE Orders
(OrderID INT IDENTITY PRIMARY KEY,
OrderDate DATE,
ShipCity VARCHAR(100),
ShipCountry VARCHAR(100)
)
GO
INSERT INTO Orders (OrderDate, ShipCity, ShipCountry)
    VALUES (GETDATE(), 'London', 'UK'),
    (GETDATE(),'Paris','France'),
    (GETDATE(),'Porto','Portugal'),
    (GETDATE(),'Vale','USA'),
    (GETDATE(),'Cusco','Peru'),
    (GETDATE(),'Montreal','Canada'),
    (GETDATE(),'Rio de Janeiro','Brazil')
GO

Here’s my latest attempt at the stored proc (which clearly doesn’t work):

CREATE PROC TestProc @Country VARCHAR(100)
AS
BEGIN
    SELECT * 
    FROM Orders o
    WHERE 
        CASE 
            WHEN @Country='Europe' THEN o.ShipCountry IN (SELECT Country FROM Countries c WHERE c.Continent='Europe')
            WHEN @Country='North America' THEN o.ShipCountry IN (SELECT Country FROM Countries c WHERE c.Continent='North America')
            WHEN @Country='South America' THEN o.ShipCountry IN (SELECT Country FROM Countries c WHERE c.Continent='South America')
            ELSE o.ShipCountry=@Country
        END
END 

I’ve also tried using a simple case rather than a searched case, but couldn’t get that to work either.

TBH, I’m thinking that the best option is to have two option parameters – @Country and @Continent, and to re-write the calling procedures to match. However, having spent quite a while working on this now, I’d like to know if it is, in fact, possible, and if so, how.

Thanks.

>Solution :

DECLARE @Country VARCHAR(100) = 'France';

SELECT * 
    FROM Orders o
    WHERE 
        o.ShipCountry IN (SELECT Country 
                          FROM Countries c 
                          WHERE c.Continent=CASE @Country WHEN '<Europe>' 
                                                         THEN 'Europe'
                                                         WHEN '<North America>'
                                                         THEN 'North America'
                                                         WHEN '<South America>'
                                                         THEN 'South America'
                                                         ELSE ''
                                                         END
                                or c.Country = @Country)

DBFIDDLE: https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=f15c9e79ff98789ec985556f76017985

EDIT: It’s even possible to do it without CASE

DECLARE @Country VARCHAR(100) = '<Europe>';

SELECT o.* 
FROM Orders o
INNER JOIN Countries c ON c.Country = o.ShipCountry
WHERE o.ShipCountry = @Country
   OR c.Continent = REPLACE(REPLACE(@Country,'<',''),'>','')

see: DBFIDDLE)

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading