How Do I Use Case Statement Column In Group By - sql

As stated by the question, I'm trying to formulate a query that has a case statement in the column results, and then I want to include that column in the query's group by statement. To give a concrete example, here is all little of what my query looks like:
SELECT SOME_TABLE_ALIAS.COLUMN1, OTHER_TABLE_ALIAS.COLUMN2,
CASE
WHEN SOME_TABLE_ALIAS.COLUMN3 IS NOT NULL THEN 'A'
ELSE 'B'
END AS CASE_COLUMN
FROM SOME_TABLE SOME_TABLE_ALIAS
... (other table joins and where clauses)
GROUP BY SOME_TABLE_ALIAS.COLUMN1, OTHER_TABLE_ALIAS.COLUMN2, CASE_COLUMN
Before coming here, I checked out a few websites, including this one, to try solve my problem. I've tried adding another alias after the CASE keyword like is shown in the linked web page but have had no luck. The error message I continue to receive is the following:
[Error] Script lines: 127-151 ----------------------
CASE_COLUMN IS NOT VALID IN THE CONTEXT WHERE IT IS USED. SQLCODE=-206, SQLSTATE=42703, DRIVER=3.53.71
Has anyone else run into the issues I'm facing and been able to use a GROUP BY on the results of a CASE statement? Any help would be appreciated. Oh, and the DB2 version is a z/OS instance, version 10 (DSN10015)

The alias isn't available to use in the GROUP BY because when GROUP BY happens the alias isn't defined yet:
Here's the order:
1.FROM
2.WHERE
3.GROUP BY
4.HAVING
5.SELECT
6.ORDER BY
You can work around that with:
SELECT column1,column2,case_column
FROM (
SELECT SOME_TABLE_ALIAS.COLUMN1, OTHER_TABLE_ALIAS.COLUMN2,
CASE
WHEN SOME_TABLE_ALIAS.COLUMN3 IS NOT NULL THEN 'A'
ELSE 'B'
END AS CASE_COLUMN
FROM SOME_TABLE SOME_TABLE_ALIAS
... (other table joins and where clauses)
) a
GROUP BY COLUMN1, COLUMN2, CASE_COLUMN
Or just use the case you use in SELECT in GROUP BY

You can either use the case as is in the group by, like this:
SELECT SOME_TABLE_ALIAS.COLUMN1, OTHER_TABLE_ALIAS.COLUMN2,
CASE
WHEN SOME_TABLE_ALIAS.COLUMN3 IS NOT NULL THEN 'A'
ELSE 'B'
END AS CASE_COLUMN
FROM SOME_TABLE SOME_TABLE_ALIAS
... (other table joins and where clauses)
GROUP BY SOME_TABLE_ALIAS.COLUMN1, OTHER_TABLE_ALIAS.COLUMN2,
CASE
WHEN SOME_TABLE_ALIAS.COLUMN3 IS NOT NULL THEN 'A'
ELSE 'B'
END
or use a sub-query like this:
select COLUMN1, COLUMN2, CASE_COLUMN
from (
SELECT SOME_TABLE_ALIAS.COLUMN1, OTHER_TABLE_ALIAS.COLUMN2,
CASE
WHEN SOME_TABLE_ALIAS.COLUMN3 IS NOT NULL THEN 'A'
ELSE 'B'
END AS CASE_COLUMN
FROM SOME_TABLE SOME_TABLE_ALIAS
... (other table joins and where clauses)
) a
GROUP BY COLUMN1, COLUMN2, CASE_COLUMN

Related

Select Case when Grouping(Column1) not working in Snowflake

I'm trying to do the following query in Snowflake:
Select case when grouping(column_1) = 'Total'
else column_1 end as column_1
,sum(column_2)
From Table
group by rollup(column_1)
But I keep getting the error: "SQL compilation error: GROUPING function cannot appear outside of SELECT, HAVING, and ORDER BY clauses."
Any suggestions on how to fix this or work arounds?
Try writing the query like this:
select (case when grouping(t.column_1) = 1
then 'Total' else column_1
end) as column_1,
sum(column_2)
From Table t
group by rollup(t.column_1);
That is, qualify the reference in the GROUP BY so it is not resolved to the column alias. Also, note that this fixes the case expression.

SSRS cannot parse SQL query

I am trying to define an SQL query in my SSRS report, but I am getting some syntax errors:
Error in SELECT clause: expression near 'WHEN'.
Missing FROM clause.
Error in SELECT clause: expression near ','.
Unable to parse query text.
The query is not that complicated, but rather a bit convoluted, but I'll try to convey at least the structure of it here:
select
(CASE WHEN columnA1 is null THEN columnA2 ELSE columnA1 END) as columnA,
(CASE WHEN columnB1 is null THEN columnB2 ELSE columnB1 END) as "custom_name_for_columnB"
from
(
(select a.columnA1, ...
from myTable a, ...
// join conditions
)
union
select * from
(select a.columnA1, ...
from myTable a, ...
// join conditions
order by someColumn) source
)
);
I don't think it really matters what the query does since I ran it in my DMBS successfully, so I'm pretty sure it's correct SQL syntax (I'm working on Oracle DB). I think what I'm not seeing is some syntax specific to SSRS. I'm completely new to it, so I don't know whether it supports the entire SQL syntax like CASE WHEN, unions etc.
As it complains about CASE (as if it doesn't recognize the syntax), try some more options:
COALESCE:
select coalesce(columnA1, columnA2) columnA,
coalesce(columnB1, columnB2) columnB
from ...
NVL:
select nvl(columnA1, columnA2) columnA,
nvl(columnB1, columnB2) columnB
from ...
DECODE:
select decode(columnA1, null, columnA2, columnA1) columnA,
decode(columnB1, null, columnB2, columnB1) columnB
from ...
Correct my query if I made too many changes, but I think there are a couple of things wrong:
SELECT (CASE WHEN t.columnA1 IS NULL THEN t.columnA2 ELSE t.columnA1 END) as columnA,
(CASE WHEN t.columnB1 IS NULL THEN t.columnB2 ELSE t.columnB1 END) as [custom_name_for_columnB]
FROM(
SELECT a.columnA1, ...
FROM myTable a, ...
JOIN conditions
UNION
SELECT * FROM
(
SELECT a.columnA1, ...
FROM m myTable a, ...
JOIN conditions
--ORDER BY someColumn --Can't have ORDER BY in subquery without TOP(n) / FOR XML.
) source
)t; --Needs an alias

How to nest a CTE (Common Table Expression)

I have the below query
With max_cm1 as (select * from tableA)
Select * ,
CASE WHEN TO_CHAR(CCP2.END_DATE,'MM/DD/YYYY') <> '09/09/9000' THEN 'CLOSED'
WHEN MAX_CM1.MAX_ROLE_CM IS NOT NULL AND HIST.PCMUID IS NOT NULL THEN 'ASSIGNED'
ELSE 'UNASSIGNED'
END STATUS
from max_cm1
Now I need to filter on the case statement. How can I do this?
You can use an alias eg: m.
With max_cm1 as (select * from tableA)
Select m.* ,
CASE WHEN TO_CHAR(CCP2.END_DATE,'MM/DD/YYYY') <> '09/09/9000' THEN 'CLOSED'
WHEN MAX_CM1.MAX_ROLE_CM IS NOT NULL AND HIST.PCMUID IS NOT NULL THEN 'ASSIGNED'
ELSE 'UNASSIGNED'
END STATUS
from max_cm1 m;
In your case, you don't need a CTE unless you are joining it with other table with some expressions in CTE. Directly you can fetch from table A with the same method if you are only interested in select '*'.
Your question is unclear. Also, the query as given is somewhat confusing, as it qualifies some columns with table names (CCP2 and HIST) that don't appear elsewhere in the query. Further, as written there seems to be no purpose to the CTE at all.
I'm assuming that what you want is to include the given CASE expression in the result set, but also use it within the WHERE clause to filter the results (e.g. WHERE CASE ... END = 'CLOSED'. The simple way to do this is to repeat the CASE expression; but of course duplicating logic is never a good choice. So the better way, which I think is the point of your question, is to include that derived column in a CTE so you can then refer to it by name in the WHERE clause.
It also looks like you are probably running into the issue of trying to select all columns (*) plus a derived column. The way around this is to qualify the * with the table name, or an alias as indicated in one of the other answers.
Putting this all together, I believe you want something like the following. I'm keeping the column expressions (e.g. HIST.PCMUID) as you wrote them although as written they make no sense. I'm guessing that tableA really represents some join of multiple tables.
WITH max_cm1 AS (
SELECT tableA.* ,
CASE WHEN TO_CHAR(CCP2.END_DATE,'MM/DD/YYYY') <> '09/09/9000' THEN 'CLOSED'
WHEN MAX_CM1.MAX_ROLE_CM IS NOT NULL AND HIST.PCMUID IS NOT NULL THEN
'ASSIGNED'
ELSE 'UNASSIGNED'
END STATUS
FROM tableA
)
SELECT *
FROM max_cm1
WHERE status = 'CLOSED'

Is there a way to use the distinct keyword inside a conditional case statement of an SQL query?

I have an SQL statement in which I would like to use the distinct keyword inside a conditional case statement like so...
SELECT
case when <condition> then distinct t.myfield
else
null
end as my_field
If I try to run the query, though, I get a 'missing expression' error.
Any suggestions?
Thanks in advance
Distinct is for the entire select statement, not a single field. You could do the following:
SELECT DISTINCT Case when <condition> then t.myfield else null end as my_field
This will affect other fields in the select statement though. An alternative would be to add it to a separate query:
SELECT case when <condition> then t.myfield else null end as my_field
from (select distinct myfield from t) as t

SQL: Alias Column Name for Use in CASE Statement

Is it possible to alias a column name and then use that in a CASE statement? For example,
SELECT col1 as a, CASE WHEN a = 'test' THEN 'yes' END as value FROM table;
I am trying to alias the column because actually my CASE statement would be generated programmatically, and I want the column that the case statement uses to be specified in the SQL instead of having to pass another parameter to the program.
This:
SELECT col1 as a,
CASE WHEN a = 'test' THEN 'yes' END as value
FROM table;
...will not work. This will:
SELECT CASE WHEN a = 'test' THEN 'yes' END as value
FROM (SELECT col1 AS a
FROM TABLE)
Why you wouldn't use:
SELECT t.col1 as a,
CASE WHEN t.col1 = 'test' THEN 'yes' END as value
FROM TABLE t;
...I don't know.
I think that MySql and MsSql won't allow this because they will try to find all columns in the CASE clause as columns of the tables in the WHERE clause.
I don't know what DBMS you are talking about, but I guess you could do something like this in any DBMS:
SELECT *, CASE WHEN a = 'test' THEN 'yes' END as value FROM (
SELECT col1 as a FROM table
) q
#OMG Ponies - One of my reasons of not using the following code
SELECT t.col1 as a,
CASE WHEN t.col1 = 'test' THEN 'yes' END as value
FROM TABLE t;
can be that the t.col1 is not an actual column in the table. For example, it can be a value from a XML column like
Select XMLColumnName.value('(XMLPathOfTag)[1]', 'varchar(max)')
as XMLTagAlias from Table
It should work. Try this
Select * from
(select col1, col2, case when 1=1 then 'ok' end as alias_col
from table)
as tmp_table
order by
case when #sortBy = 1 then tmp_table.alias_col end asc
I use CTEs to help compose complicated SQL queries but not all RDBMS' support them. You can think of them as query scope views. Here is an example in t-sql on SQL server.
With localView1 as (
select c1,
c2,
c3,
c4,
((c2-c4)*(3))+c1 as "complex"
from realTable1)
, localView2 as (
select case complex WHEN 0 THEN 'Empty' ELSE 'Not Empty' end as formula1,
complex * complex as formula2
from localView1)
select *
from localView2
Nor in MsSql
SELECT col1 AS o, e = CASE WHEN o < GETDATE() THEN o ELSE GETDATE() END
FROM Table1
Returns:
Msg 207, Level 16, State 3, Line 1
Invalid column name 'o'.
Msg 207, Level 16, State 3, Line 1
Invalid column name 'o'.
However if I change to CASE WHEN col1... THEN col1 it works
If you write only equal condition just:
Select Case columns1 When 0 then 'Value1'
when 1 then 'Value2' else 'Unknown' End
If you want to write greater , Less then or equal you must do like this:
Select Case When [ColumnsName] >0 then 'value1' When [ColumnsName]=0 Or [ColumnsName]<0 then
'value2'
Else
'Unkownvalue' End
From tablename
Thanks
Mr.Buntha Khin
SELECT
a AS [blabla a],
b [blabla b],
CASE c
WHEN 1 THEN 'aaa'
WHEN 2 THEN 'bbb'
ELSE 'unknown'
END AS [my alias],
d AS [blabla d]
FROM mytable
Not in MySQL. I tried it and I get the following error:
ERROR 1054 (42S22): Unknown column 'a' in 'field list'
In MySql, alice name may not work, therefore put the original column name in the CASE statement
SELECT col1 as a, CASE WHEN col1 = 'test' THEN 'yes' END as value FROM table;
Sometimes above query also may return error, I don`t know why (I faced this problem in my two different development machine). Therefore put the CASE statement into the "(...)" as below:
SELECT col1 as a, (CASE WHEN col1 = 'test' THEN 'yes' END) as value FROM table;
Yes, you just need to add a parenthesis :
SELECT col1 as a, (CASE WHEN a = 'test' THEN 'yes' END) as value FROM table;
make it so easy.
select columnnameshow = (CASE tipoventa
when 'CONTADO' then 'contadito'
when 'CREDITO' then 'cred'
else 'no result'
end) from Promocion.Promocion