Combing CASE WHEN with NVL() and GROUP BY - sql

I do a CASE WHEN in my SELECT to convert any null into 'None'. I also want to take a specific non-null value (e.g. 'X') and treat this the same as the null values (e.g. make them all 'None').
I do something like this:
SELECT
CASE WHEN Val = 'X' THEN 'None' ELSE NVL(Val, 'None') END ValCol
FROM tbl
GROUP BY Val
What I end up with is two rows of 'None'; in essence the two 'None' values are being treated separately.
How do I combine them?

The problem is the GROUP BY. You are grouping by Val, so all rows with Val as X are grouped together and all rows where Val IS NULL are grouped together. This actually results in 2 rows, but are displayed with the same value because of your CASE expression.
You can solve this by grouping with your CASE instead of Val:
SELECT
CASE WHEN Val = 'X' THEN 'None' ELSE NVL(Val, 'None') END ValCol
FROM
tbl
GROUP BY
CASE WHEN Val = 'X' THEN 'None' ELSE NVL(Val, 'None') END
As side note, I find the following CASE a little more expressive:
CASE WHEN Val = 'X' OR Val IS NULL THEN 'None' ELSE Val END

Try this:
SELECT
CASE WHEN Val = 'X' THEN 'None' ELSE NVL(Val, 'None') END ValCol
FROM tbl
GROUP BY (CASE WHEN Val = 'X' THEN 'None' ELSE NVL(Val, 'None') END)

You can do this by using the expression instead of the column in the GROUP BY clause like this:
SELECT CASE WHEN Val = 'X' THEN 'None' ELSE NVL(Val, 'None') END ValCol
FROM tbl
GROUP
BY CASE WHEN Val = 'X' THEN 'None' ELSE NVL(Val, 'None') END
A second way is to use a sub select for the CASE and to group in an outer select
SELECT ValCol
FROM(SELECT CASE WHEN Val = 'X' THEN 'None' ELSE NVL(Val, 'None') END ValCol
FROM tbl
)
GROUP
BY ValCOL
I would prefer the second way because it's more readable.

Related

case statement to find one value

I'm trying to show one row per id but it is returning three.
If the id has a 'y' then it should show a 'y'.
If it shows a 'y' and 'r' it should be 'y'.
If it has 'y', 'r', 'n' it should be 'y'.
If it is just id and 'r' it should be 'r' and id and just 'n' then 'n'.
I can't seem to get it to work using a case statement. Any ideas? Thanks.
I've tried this:
,CASE WHEN result = 'Y' THEN 'Y'
WHEN result = 'Y' AND result = 'R') THEN 'Y'
WHEN result = 'R' THEN 'R'
ELSE 'N' END AS CARE_PLAN
What it is returning:
ID result
3434 'y'
3434 'r'
3434 'n'
You can use Listagg function,
Writing a subquery and DISTINCT then use Listagg function.
SELECT id, Listagg (result, ', ')
within GROUP (ORDER BY result) as CARE_PLAN
FROM (SELECT DISTINCT id,
( CASE
WHEN result = 'Y' THEN 'Y'
WHEN result = 'Y'
AND result = 'R' THEN 'Y'
WHEN result = 'R' THEN 'R'
ELSE 'N'
END ) AS result
FROM t) T
GROUP BY id
sqlfiddle:http://sqlfiddle.com/#!4/02cd5/2
[Results]:
| ID | CARE_PLAN |
|------|-----------|
| 1234 | N, R, Y |
It shall be proper to use ASCII and CHR functions for your case instead of using CASE .. WHEN, as in the following :
SELECT ID, CHR(MAX(ASCII(result))) AS CARE_PLAN
FROM TAB
GROUP BY ID
ORDER BY ID;
SQL Fiddle Demo
You would seem to want aggregation with some conditional logic:
select id,
(case when sum(case when result = 'y' then 1 else 0 end) > 0 then 'y'
when sum(case when result = 'r' then 1 else 0 end) > 0 then 'r'
when min(result) = max(result) and min(result) = 'n' then 'n'
else '?'
end) as new_result
from t
group by id;
If there are only those three values, then perhaps this simplified logic works:
select id, max(result) as new_result
from t
group by id;

How to return 'blank' using Sum function in Sql, if Sum is resulting 0 in SQL

I am using Sql Server 2008. I am adding some column value using Sum function. Like the code below:
SELECT 'RCOAuthorizer LMS',
'' AS Consumer_Loan,
'' AS Auto_Loan,
'' AS Credit_Card,
SUM(CASE
WHEN sq2.loan_type = 'Loan Amendment' THEN sq2.user_count
ELSE ''
END ) AS Loan_Amendment,
SUM(CASE
WHEN sq2.loan_type = 'Pre-Payment' THEN sq2.user_count
ELSE ''
END ) AS Pre_Payment,
SUM(CASE
WHEN sq2.loan_type = 'Corporate Credit card' THEN sq2.user_count
ELSE ''
END ) AS Corporate_Credit_card,
'' AS Auto_Payment_Release,
'' AS Car_Mulkiya
FROM
( SELECT 'RCOAuthorizer' AS ws_name,
'Loan Amendment' AS loan_type,
COUNT (DISTINCT a.bpm_referenceno) AS user_count,
a.user_id AS user_id
FROM BM_LMS_DecisionHistoryGrid a
INNER JOIN
( SELECT m.bpm_referenceno
FROM BM_LMS_EXTTABLE m
WHERE m.request_type = 'Loan Amendment' ) sq1 ON a.bpm_referenceno = sq1.bpm_referenceno
WHERE workstep_name = 'RCOAuthorizer'
GROUP BY a.user_id
UNION SELECT 'RCOAuthorizer',
'Pre-Payment',
COUNT (DISTINCT a.bpm_referenceno), a.user_id
FROM BM_LMS_DecisionHistoryGrid a
INNER JOIN
( SELECT m.bpm_referenceno
FROM BM_LMS_EXTTABLE m
WHERE m.request_type = 'Pre-Payment' ) sq1 ON a.bpm_referenceno = sq1.bpm_referenceno
WHERE workstep_name = 'RCOAuthorizer'
GROUP BY a.user_id
UNION SELECT 'RCOAuthorizer',
'Corporate Credit card',
COUNT (DISTINCT a.bpm_referenceno), a.user_id
FROM BM_LMS_DecisionHistoryGrid a
INNER JOIN
( SELECT m.bpm_referenceno
FROM BM_LMS_EXTTABLE m
WHERE m.request_type = 'Corporate Credit card' ) sq1 ON a.bpm_referenceno = sq1.bpm_referenceno
WHERE workstep_name = 'RCOAuthorizer'
GROUP BY a.user_id ) sq2
GROUP BY sq2.ws_name
The above query will return Sum of all the numbers available in 'a' column. But in case, there is no record, then it will return '0' as result.
I require that if there is no record, it must show blank instead of showing '0'. How to handle the same.
To start, you don't need an ISNULL with a back value of 0 (the neutral for adding) inside a SUM aggregate, as the SUM already ignores NULL values. So SUM(ISNULL(Column, 0)) is equal to SUM(Column) (but different from ISNULL(SUM(Column), 0)!).
Seems that you want a VARCHAR result instead of a numeric one. You can solve this with a CASE.
Select
CASE WHEN Sum(a) = 0 THEN '' ELSE CONVERT(VARCHAR(100), Sum(a)) END
from
table;
If you don't want to repeat the SUM expression:
;WITH SumResult AS
(
Select CONVERT(VARCHAR(100), Sum(a)) AS SumTotal
from table
)
SELECT
CASE WHEN R.SumTotal = '0' THEN '' ELSE R.SumTotal END
FROM
SumResult AS R
Keep in mind that in these both cases, if there is no record to calculate the sum from, the result will be NULL.
EDIT: There is no point in adding '' inside your SUM, as it's converted to 0 to be able to sum. The solution is still the same as I posted before.
Change
SUM(CASE
WHEN sq2.loan_type = 'Pre-Payment' THEN sq2.user_count
ELSE ''
END ) AS Pre_Payment,
for
CASE
WHEN SUM(CASE WHEN sq2.loan_type = 'Pre-Payment' THEN sq2.user_count END) = 0 THEN ''
ELSE CONVERT(VARCHAR(100), SUM(CASE WHEN sq2.loan_type = 'Pre-Payment' THEN sq2.user_count)) END AS Pre_Payment,
Just try this ( use isnull again ):
Select isnull(Sum(isnull(a,0)),0) from table_;
I used table_ instead of table, because table is a reserved keyword.
SQL Fiddle Demo

Case Expression on a created column using Microsoft SQL

Within a view I put put together a select statement within a case and delcared it as a column. The column name is 'IR2'
How can I case off of the column 'IR2'?
I end up getting an error which says 'Invalid Column Name 'IR2'.
What are my work around options?
case when r.ana = 'nh3' and r.serv='energy' and exists( select 1 from results x where x.no=r.no and x.ana='nh3' and x.sa='rejected' and x.serv <> 'energy')
then '*' else r.sa end as IR2,
CASE IR2 WHEN 'Released' then
''
ELSE
'*'
END AS IR
You can use a subquery or CTE. But another fun way in SQL Server is using outer apply:
select v.IR2,
(case IR2 when 'Released' then '' else '*' end) as ir
from . . . outer apply
(values (case when r.ana = 'nh3' and r.serv='energy' and
exists( select 1 from results x where x.no=r.no and x.ana='nh3' and x.sa='rejected' and x.serv <> 'energy')
then '*' else r.sa
end)
) v(IR2)
CTE would be the best choice. If you want to continue with current statement, you need to put a copy of the case statement in other case statement. Very messy code.
SELECT
case when r.ana = 'nh3' and r.serv='energy' and
exists( select 1 from results x where x.no=r.no and x.ana='nh3' and x.sa='rejected' and x.serv <> 'energy')
then '*' else r.sa end as IR2,
CASE
(case when r.ana = 'nh3' and r.serv='energy'
and exists( select 1 from results x where x.no=r.no and x.ana='nh3' and x.sa='rejected' and x.serv <> 'energy')
then '*' else r.sa end)
WHEN 'Released' then
''
ELSE
'*'
END AS IR

SQL Server : case statement

I have table named boolean which contain 'true' and/or 'false' values as strings in one column.
I have problem to create case statement to show me whether there are only 'true' or 'false' or 'both' values
Example 1:
'true'
'true'
result:'true'
Example 2:
'false'
'false'
'false'
Result: 'false'
Example 3:
'true'
'false'
'true'
Result: 'both'
Edit:
case statement should look like:
case
when "column content are only true values" then 'true'
when "column content are only false values" then 'false'
else 'both'
end
You could aggregate the max and min of the column, and then evaluate the results - if they are the same, there's only one value in the column. If not, there must be both. Note that since these are string representations the values are sorted lexicographically:
SELECT CASE WHEN MAX(col) = MIN(col) THEN MAX(col) ELSE 'both' END
FROM my_table
SELECT CASE WHEN MIN(Col) <> MAX(Col) THEN
'Both'
ELSE
MIN(Col)
END
FROM YourTable
select case when count(distinct bool_column) = 2 then 'both'
when sum(case when bool_column = 'false' then 1 end) > 0 then 'false'
else 'true'
end as result
from your_table

SQL case with different fields to check from same table

I have the following problem:
I have a select statement that includes a case part. Up til there it is easy the problem is that the case includes a check against another field in the same table.
select h.id,
case h.value
when 'P' then 'test'
when '' then 'failed'
when 'D' then 'passed'
else null end
as info,
b.text,
case h.diag
when h.value = '' [or 'failed' not sure tried both and didn't work]
else h.diag end
as diag1, h.date from valuetab h, texttab b where h.id=b.id
I want to have h.diag only to show values when h.value is not failed.
I always get the mistake that the = should be concat.. but that doesn't make sense in my eyes.
Any ideas??
Thats for all your help.
You can also write a case statement with your expression in a different place i.e.
SELECT CASE WHEN X = 1 THEN 'Y' WHEN X = 2 THEN 'Z'
I think what you want to do is something more like this:
SELECT CASE WHEN h.value = '' THEN h.diag end
Use the other form of case statement, which doesn't specify a column you want to look at:
select case
when column1 = 2 then 'Foo'
when other_column = 'blah' then 'Bar'
end
from table
The problem with using case column1 when... is that it implicitly compares column1 to each when clause. You can't then include a comparison to some other column in it.
You are missing a THEN portion of the WHEN clause, and specifying a condition where you could specify a value:
case h.value
when '' THEN NULL
else h.diag end
Ok got it....
after the 2nd case the "h.diag" must be removed....
so it is
case
when h.value = '' then null
else h.diag end
as diag1,