Reputation: 1817
I have a view which has a complicated CASE statement to determine the value of one of the columns.
SELECT a.itemcode, count(*) total, b.foo
CASE
WHEN foo IN ('aab', 'aac')
THEN 1
WHEN foo IN ('qqq', 'fff')
THEN 2
WHEN foo IN ('foo', 'bar')
THEN 10 % count(*)
ELSE 9 % count(*)
END AS other_total
FROM a INNER JOIN b ON a.itemcode = b.itemcode
GROUP BY itemcode, foo
I want to add a check for the value of the column other_total. If it is 0
, I want to set the value to 1
.
Obviously I could surround the whole thing in a CASE
statement...
CASE ( CASE
WHEN foo IN ('aab', 'aac')
THEN 1
WHEN foo IN ('qqq', 'fff')
THEN 2
WHEN foo IN ('foo', 'bar')
THEN 10 % count(*)
ELSE 9 % count(*)
END )
WHEN 0 THEN 1
ELSE CASE
WHEN foo IN ('aab', 'aac')
THEN 1
WHEN foo IN ('qqq', 'fff')
THEN 2
WHEN foo IN ('foo', 'bar')
THEN 10 % count(*)
ELSE 9 % count(*)
END
END AS other_total
But this is just a bit messy and seems like there should be an easier way.
Is there another function, similar to ISNULL()
, that would allow me to change the value of the column if it equals zero?
ANSWER
Thanks to gofr1's answer I was able to work this one out. I used the NULLIF function to return NULL if the case statement was equal to 0, then surrounded with an ISNULL function to set the value to 1 if the NULLIF function returned NULL.
SELECT a.itemcode, count(*) total, b.foo,
ISNULL (
NULLIF (
CASE
WHEN foo IN ('aab', 'aac')
THEN 1
WHEN foo IN ('qqq', 'fff')
THEN 2
WHEN foo IN ('foo', 'bar')
THEN 10 % count(*)
ELSE 9 % count(*)
END
), 0)
), 1) other_total
FROM a INNER JOIN b ON a.itemcode = b.itemcode
GROUP BY itemcode, foo
Upvotes: 6
Views: 34067
Reputation: 15977
You can use NULLIF
Returns a null value if the two specified expressions are equal.
CASE WHEN
NULLIF(
CASE WHEN foo IN ('aab', 'aac') THEN 1
WHEN foo IN ('qqq', 'fff') THEN 2
WHEN foo IN ('foo', 'bar') THEN 10 % count(*)
ELSE 9 % count(*)
END
,0) IS NULL THEN 0 ELSE 1 END
AS other_total
If value = 0
then it becomes NULL
else the value is in output. Then we use CASE WHEN value IS NULL then 0 else 1
.
Upvotes: 6
Reputation: 17161
SELECT NullIf(<your_code>, 0) AS zero_to_null
, Coalesce(NullIf(<your_code>, 0), 1) AS zero_to_null_to_one
or
SELECT CASE WHEN other_total = 0 THEN 1 ELSE other_total END AS new_total
FROM (
<your_code>
) AS a_subquery
Upvotes: 3
Reputation: 24763
use DERIVED QUERY or CTE
-- Derived query
SELECT itemcode, total, foo, case when other_total = 0 then 1 else other_total end as other_total
FROM
(
SELECT a.itemcode, count(*) total, b.foo
CASE
WHEN foo IN ('aab', 'aac')
THEN 1
WHEN foo IN ('qqq', 'fff')
THEN 2
WHEN foo IN ('foo', 'bar')
THEN 10 % count(*)
ELSE 9 % count(*)
END AS other_total
FROM a INNER JOIN b ON a.itemcode = b.itemcode
GROUP BY itemcode, foo
) d
OR
you can just use CASE on the last 2 expression of the CASE WHEN... since that is the only 2 places that will gives you 0.
WHEN foo IN ('foo', 'bar')
THEN CASE WHEN 10 % count(*) = 0 THEN 1 ELSE 10 % count(*) END
ELSE CASE WHEN 9 % count(*) = 0 THEN 1 ELSE 9 % count(*) END
END AS other_total
Upvotes: 0