Solved

# Nested Case Statement Syntax

Posted on 2013-01-03
798 Views
I am trying to write a nested case statement to look back at the 3 prior months and give me an average. But I keep getting an error. Where am I wrong?

CASE
WHEN LatestMonthNum=2
THEN
CASE
WHEN MONTH(TodayDate)=1 and YEAR(TodayDate)=LatestYearNum or
MONTH(TodayDate)=12 and YEAR(TodayDate)=LatestYearNum -1 or
MONTH(TodayDate)=11 and YEAR(TodayDate)=LatestYearNum -1
THEN ConvertedQuantity/3
ELSE CASE WHEN LatestMonthNum=1 THEN
CASE WHEN MONTH(TodayDate)=12 and YEAR(TodayDate)=LatestYearNum-1 or
MONTH(TodayDate)=11 and YEAR(TodayDate)=LatestYearNum -1 or
MONTH(TodayDate)=10 and YEAR(TodayDate)=LatestYearNum -1
THEN ConvertedQuantity/3
ELSE CASE WHEN MONTH(TodayDate)= LatestMonthNum-1 and YEAR(TodayDate)=LatestYearNum or MONTH(TodayDate)= LatestMonthNum-2 and YEAR(TodayDate)=LatestYearNum or MONTH(TodayDate)= LatestMonthNum-3 and YEAR(TodayDate)=LatestYearNum
then ConvertedQuantity/3
else null

END as 'ThreeMoAvg'
0
Question by:nirajkrishna

LVL 45

Expert Comment

ID: 38741767
Howdy...

Indenting the code makes it really easy to see.  :)

``````CASE WHEN LatestMonthNum=2
THEN CASE WHEN MONTH(TodayDate)=1 and YEAR(TodayDate)=LatestYearNum or
MONTH(TodayDate)=12 and YEAR(TodayDate)=LatestYearNum -1 or
MONTH(TodayDate)=11 and YEAR(TodayDate)=LatestYearNum -1
THEN ConvertedQuantity/3
ELSE CASE WHEN LatestMonthNum=1
THEN CASE WHEN MONTH(TodayDate)=12 and YEAR(TodayDate)=LatestYearNum-1 or
MONTH(TodayDate)=11 and YEAR(TodayDate)=LatestYearNum -1 or
MONTH(TodayDate)=10 and YEAR(TodayDate)=LatestYearNum -1
THEN ConvertedQuantity/3
ELSE CASE WHEN MONTH(TodayDate)= LatestMonthNum-1 and YEAR(TodayDate)=LatestYearNum or
MONTH(TodayDate)= LatestMonthNum-2 and YEAR(TodayDate)=LatestYearNum or
MONTH(TodayDate)= LatestMonthNum-3 and YEAR(TodayDate)=LatestYearNum
then ConvertedQuantity/3
else null
END as 'ThreeMoAvg'
``````

It's really tough to see what you're trying to achieve.  Can you explain it?  The SQL should be easy.  :)

Kent
0

LVL 65

Expert Comment

ID: 38741769
<knee-jerk reaction>
I see AND and OR in the same clauses, but no parentheses ( ) to determine order of execution.

I'm guessing the first block should be this:

CASE WHEN
(MONTH(TodayDate)=1 and YEAR(TodayDate)=LatestYearNum) or
(MONTH(TodayDate)=12 and YEAR(TodayDate)=LatestYearNum -1) or
(MONTH(TodayDate)=11 and YEAR(TodayDate)=LatestYearNum -1)
THEN ConvertedQuantity/3

Without the parentheses ( ), it's going to do each and .. or ... and as an entire set, and since Month(TodayDate) is likely a single value per row, it'll never evaluate as True and return the THEN expression, only the ELSE expression.
0

Author Comment

ID: 38741772
This is just the calculated column and not the whole query. I am cross joined to a single row table that gives me the most recent date and  latest month number (LatestMonthNum) and latest year (LatestYearNum)
0

LVL 45

Accepted Solution

Kdo earned 500 total points
ID: 38741792
Every CASE clause must have a matching END.  The indented code above shows that a few well placed END statements are needed.  I think that you want something like this, but it's hard to know.  Keep in mind that if a CASE statement doesn't find a match, NULL is returned so this may take some more work.

``````CASE WHEN LatestMonthNum=2
THEN CASE WHEN MONTH(TodayDate)=1 and YEAR(TodayDate)=LatestYearNum or
MONTH(TodayDate)=12 and YEAR(TodayDate)=LatestYearNum -1 or
MONTH(TodayDate)=11 and YEAR(TodayDate)=LatestYearNum -1
THEN ConvertedQuantity/3
END
ELSE CASE WHEN LatestMonthNum=1
THEN CASE WHEN MONTH(TodayDate)=12 and YEAR(TodayDate)=LatestYearNum-1 or
MONTH(TodayDate)=11 and YEAR(TodayDate)=LatestYearNum -1 or
MONTH(TodayDate)=10 and YEAR(TodayDate)=LatestYearNum -1
THEN ConvertedQuantity/3
END
END
ELSE CASE WHEN MONTH(TodayDate)= LatestMonthNum-1 and YEAR(TodayDate)=LatestYearNum or
MONTH(TodayDate)= LatestMonthNum-2 and YEAR(TodayDate)=LatestYearNum or
MONTH(TodayDate)= LatestMonthNum-3 and YEAR(TodayDate)=LatestYearNum
then ConvertedQuantity/3
else null
END
END as 'ThreeMoAvg'
``````
0

Author Comment

ID: 38741797
I am trying to say if the LatestMonthNum = 2 or 1 which means Jan or Feb then look at the latest month number and use the appropriate 3 prior months totals divided by 3 to give me an average. If it is not Jan or Feb then look at the data and when the month falls into the 3 prior months of today then add it to this column and divide it by 3 otherwise leave blank.

I am making a quick daily report that shows the current months performance (convertedQuantity) vs last month vs 3 prior month average.
0

LVL 15

Expert Comment

ID: 38741809
as kdo said, every case should finish with an end. Try to change your expression by the expression added by kdo
0

LVL 45

Expert Comment

ID: 38741812
All that this complicated CASE statement does is divide ConvertedQuantity by 3.  Or not.

You probably want record selection (the WHERE filter) to determine which rows to process and just divide by 3.
0

Author Closing Comment

ID: 38742184
This worked perfectly except for at the end I had to add one more "END" before the "END AS". Thanks!
0

## Featured Post

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The Delta outage: 650 cancelled flights, more than 1200 delayed flights, thousands of frustrated customers, tens of millions of dollars in damages – plus untold reputational damage to one of the world’s most trusted airlines. All due to a catastroph…
Never store passwords in plain text or just their hash: it seems a no-brainier, but there are still plenty of people doing that. I present the why and how on this subject, offering my own real life solution that you can implement right away, bringin…
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …