Reputation: 5823
I'm writing an SQL Query, where a few of the columns returned need to be calculated depending on quite a lot of conditions.
I'm currently using nested case statements, but its getting messy. Is there a better (more organised and/or readable) way?
(I am using Microsoft SQL Server, 2005)
A simplified example:
SELECT
col1,
col2,
col3,
CASE
WHEN condition
THEN
CASE
WHEN condition1
THEN
CASE
WHEN condition2
THEN calculation1
ELSE calculation2
END
ELSE
CASE
WHEN condition2
THEN calculation3
ELSE calculation4
END
END
ELSE
CASE
WHEN condition1
THEN
CASE
WHEN condition2
THEN calculation5
ELSE calculation6
END
ELSE
CASE
WHEN condition2
THEN calculation7
ELSE calculation8
END
END
END AS 'calculatedcol1',
col4,
col5 -- etc
FROM table
Upvotes: 242
Views: 1065392
Reputation: 408
Less complex format. Make sure keep the indentation as it is to not to be lost in ENDs.
SELECT
CASE WHEN 1=1 THEN
CASE
WHEN 11=11 THEN CASE WHEN 111=111 THEN '1-11-111' END
WHEN 12=12 THEN CASE WHEN 122=122 THEN '1-12-122' END
WHEN 13=13 THEN CASE WHEN 133=133 THEN '1-13-133' END
END
ELSE
CASE WHEN 2=2 THEN
CASE
WHEN 21=21 THEN CASE WHEN 211=211 THEN '2-21-211' END
WHEN 22=22 THEN CASE WHEN 222=222 THEN '2-22-222' END
END
ELSE
CASE WHEN 3=3 THEN
CASE
WHEN 31=31 THEN CASE WHEN 311=311 THEN '3-31-311' END
WHEN 32=32 THEN CASE WHEN 322=322 THEN '3-32-322' END
END
ELSE
CASE WHEN 4=4 THEN
CASE
WHEN 41=41 THEN CASE WHEN 411=411 THEN '4-41-411' END
WHEN 42=42 THEN CASE WHEN 412=412 THEN '4-42-412' END
END
ELSE
CASE
WHEN 51=51 THEN CASE WHEN 511=511 THEN '51-511' END
WHEN 52=52 THEN CASE WHEN 512=512 THEN '52-512' END
WHEN 53=53 THEN CASE WHEN 513=513 THEN '53-513' END
WHEN 54=54 THEN CASE WHEN 514=514 THEN '54-514' END
END
END
END
END
END
AS Sku
FROM YourTable
Upvotes: 2
Reputation: 643
You can combine multiple conditions to avoid the situation:
CASE WHEN condition1 = true AND condition2 = true THEN calculation1
WHEN condition1 = true AND condition2 = false THEN calculation2
ELSE 'what so ever' END,
Upvotes: 55
Reputation: 279
This example might help you, the picture shows how SQL case statement will look like when there are if and more than one inner if loops
Upvotes: 4
Reputation: 503
I went through this and found all the answers super cool, however wants to add to answer given by @deejers
SELECT
col1,
col2,
col3,
CASE
WHEN condition1 THEN calculation1
WHEN condition2 THEN calculation2
WHEN condition3 THEN calculation3
WHEN condition4 THEN calculation4
WHEN condition5 THEN calculation5
END AS 'calculatedcol1',
col4,
col5 -- etc
FROM table
you can make ELSE optional as its not mandatory, it is very helpful in many scenarios.
Upvotes: 4
Reputation:
Here's a simple solution to the nested "Complex" case statment: --Nested Case Complex Expression
select datediff(dd,Invdate,'2009/01/31')+1 as DaysOld,
case when datediff(dd,Invdate,'2009/01/31')+1 >150 then 6 else
case when datediff(dd,Invdate,'2009/01/31')+1 >120 then 5 else
case when datediff(dd,Invdate,'2009/01/31')+1 >90 then 4 else
case when datediff(dd,Invdate,'2009/01/31')+1 >60 then 3 else
case when datediff(dd,Invdate,'2009/01/31')+1 >30 then 2 else
case when datediff(dd,Invdate,'2009/01/31')+1 >30 then 1 end
end
end
end
end
end as Bucket
from rm20090131atb
Just make sure you have an end statement for every case statement
Upvotes: 16
Reputation: 4066
We can combine multiple conditions together to reduce the performance overhead.
Let there are three variables a b c on which we want to perform cases. We can do this as below:
CASE WHEN a = 1 AND b = 1 AND c = 1 THEN '1'
WHEN a = 0 AND b = 0 AND c = 1 THEN '0'
ELSE '0' END,
Upvotes: 8
Reputation: 3507
Wrap all those cases into one.
SELECT
col1,
col2,
col3,
CASE
WHEN condition1 THEN calculation1
WHEN condition2 THEN calculation2
WHEN condition3 THEN calculation3
WHEN condition4 THEN calculation4
WHEN condition5 THEN calculation5
ELSE NULL
END AS 'calculatedcol1',
col4,
col5 -- etc
FROM table
Upvotes: 124
Reputation: 8640
I personally do it this way, keeping the embedded CASE expressions confined. I'd also put comments in to explain what is going on. If it is too complex, break it out into function.
SELECT
col1,
col2,
col3,
CASE WHEN condition THEN
CASE WHEN condition1 THEN
CASE WHEN condition2 THEN calculation1
ELSE calculation2 END
ELSE
CASE WHEN condition2 THEN calculation3
ELSE calculation4 END
END
ELSE CASE WHEN condition1 THEN
CASE WHEN condition2 THEN calculation5
ELSE calculation6 END
ELSE CASE WHEN condition2 THEN calculation7
ELSE calculation8 END
END AS 'calculatedcol1',
col4,
col5 -- etc
FROM table
Upvotes: 43
Reputation: 5002
You could try some sort of COALESCE trick, eg:
SELECT COALESCE( CASE WHEN condition1 THEN calculation1 ELSE NULL END, CASE WHEN condition2 THEN calculation2 ELSE NULL END, etc... )
Upvotes: 223
Reputation: 61233
a user-defined function may server better, at least to hide the logic - esp. if you need to do this in more than one query
Upvotes: 8