Select two columns based on the same conditional statement SQL - sql

I have a select statement which resembles something like this
SELECT
CASE WHEN <SOME-CONDN_1> THEN 'value1' ELSE '' ||
CASE WHEN <SOME-CONDN_2> THEN 'value2' ELSE '' ||
CASE WHEN <SOME-CONDN_3> THEN 'value3' ELSE '' AS value_column,
CASE WHEN <SOME-CONDN_1> THEN 'name1' ELSE '' ||
CASE WHEN <SOME-CONDN_2> THEN 'name2' ELSE '' ||
CASE WHEN <SOME-CONDN_3> THEN 'name3' ELSE '' AS name_column
FROM data_table
--<REST OF THE QUERY>
The conditional statement is something like data_table.data_column ILIKE value1 and so on.
Since I'm doing the same conditioning statement twice (and it involves some string matching using ILIKE) I was wondering if I could club them and make it more efficient.
Would the same be possible using SQL statements?

Option 1: not quite sure if this variant of CASE works for PostgreSQL...
select case cond_num when
1 then 'value1'
when 2 then 'value2',
when 3 then 'value3' else null end as value_column,
case cond_num when
1 then 'name1'
when 2 then 'name2',
when 3 then 'name3' else null end as name_column
from (
select data_table.*,
case when <some_condition_1> then 1
when <some_condition_2> then 2
when <some_condition_3> then 3 else 0 end as cond_num
from data_table
) screened_table
;
Option 2:
select case when
cond1 = 1 then 'value1'
when cond2 = 1 then 'value2',
when cond3 = 1 then 'value3' else null end as value_column,
case when
cond1 = 1 then 'name1'
when cond2 = 1 then 'name2',
when cond3 = 1 then 'name3' else null end as name_column
from (
select data_table.*,
case when <some_condition_1> then 1 else 0 as cond1,
case when <some_condition_2> then 1 else 0 as cond2,
case when <some_condition_3> then 1 else 0 as cond3
from data_table
) screened_table
;
Option 3 - note if the conditions are not exclusive may return multiple rows. Will not return rows from data_table in which no conditions are true.
select rslt.name, rslt.value
from data_table, (
select 1 as cond, 'value1' as value, 'name1' as name
union all
select 2 as cond, 'value2' as value, 'name2' as name
union all
select 3 as cond, 'value3' as value, 'name3' as name
) rslt
WHERE (<some_condition_1> and rslt.cond = 1) OR
(<some_condition_2> and rslt.cond = 2) OR
(<some_condition_3> and rslt.cond = 3)
;

Assuming the results are both strings you can use an array to make things simpler.
SELECT a[1],a[2], ...
FROM (SELECT CASE
WHEN <SOME-CONDN_1> THEN ARRAY['value1','name1']
WHEN <SOME-CONDN_2> THEN ARRAY['value2','name2']
WHEN <SOME-CONDN_3> THEN ARRAY['value3','name3']
ELSE '' AS a
FROM ...
);
If the result values are not all the same type you can do the same thing using a ROW() constructor, but you will need to define a type in order to get the values individually "back out of the row".

Related

Sql query to create following tables

use the below table 1 to generate table 2
Table 1
Col1 A B C
------------------
N1 1 0 0
N2 0 1 0
N3 1 0 0
Table 2
output
new_col
-------
N1 A
N2 B
N3 A
Also how to use Table 2 to generate table 1 above
Following SQL query can be help to get requested output:
SELECT Col1,IF(A=1,'A',IF(B=1,'B','C')) AS result FROM `table_name`;
You can use conditinal with CONCAT() Function :
SELECT CONCAT(col1,' ',
CASE WHEN A = 1 THEN 'A' ELSE '' END,
CASE WHEN B = 1 THEN 'B' ELSE '' END,
CASE WHEN C = 1 THEN 'C' ELSE '' END)
FROM table1
provided you're on a DBMS with brand name such as MySQL, PostGRES, SQL Server. As an example, Oracle DB won't allow using more than two arguments for CONCAT() Function.
In order to create table2, use for most of the DBMS :
CREATE TABLE table2 AS
SELECT CONCAT(col1,' ',
CASE WHEN A = 1 THEN 'A' ELSE '' END,
CASE WHEN B = 1 THEN 'B' ELSE '' END,
CASE WHEN C = 1 THEN 'C' ELSE '' END) AS new_col
FROM table1
except for SQL Server in which prefer using :
SELECT CONCAT(col1,' ',
CASE WHEN A = 1 THEN 'A' ELSE '' END,
CASE WHEN B = 1 THEN 'B' ELSE '' END,
CASE WHEN C = 1 THEN 'C' ELSE '' END) AS new_col
INTO table2
FROM table1
In order to implement a reverse engineering(go back to original table), you need to consider the dialectics for each seperate database to handle string values. Assume you're using MySQL DB, then consider using :
CREATE TABLE table3 AS
SELECT SUBSTRING(new_col,1,instr(new_col,' ')-1) AS col1,
CASE WHEN instr(new_col,'A') > 0 THEN 1 ELSE 0 END AS A,
CASE WHEN instr(new_col,'B') > 0 THEN 1 ELSE 0 END AS B,
CASE WHEN instr(new_col,'C') > 0 THEN 1 ELSE 0 END AS C
FROM table2
where I used a different table name (table3), since table1 already exists.
Demo
Btw, if Oracle DB is the case, then use :
SELECT CONCAT(CONCAT(col1,' '),
CASE WHEN A = 1 THEN 'A' ELSE '' END||
CASE WHEN B = 1 THEN 'B' ELSE '' END||
CASE WHEN C = 1 THEN 'C' ELSE '' END) AS new_col
FROM table1
You can use one case statement. This works in Oracle.
SELECT col1
|| CASE
WHEN A = 1
THEN 'A'
WHEN B = 1
THEN 'B'
WHEN C = 1
THEN 'C'
END
NEW_COL
FROM table1
It is unclear what you want when there are multiple "1"s in a row. This is a simple solution:
select id, A from t where A = 1
union all
select id, B from t where B = 1
union all
select id, C from t where C = 1;
In databases that support lateral joins, I would recommend:
select t.id, v.which
from t cross join lateral
(values ('A', t.A), ('B', B), ('C', C)
) v(which, val)
where val = 1;

ORACLE: USE RESULT OF CASE-WHEN-STATEMENT

I have a huge query and I am wondering if it is in Oracle possible
to get the result of a case-when-statement and use it for comparison? My CASE-STATEMENT is declared in the Select-Statement and it looks like this.
SELECT........
(CASE
WHEN (Select 1 from DUAL) = 1 THEN 'TEST'
ELSE 'TEST2'
END) AS TEST;
Now I want to get the result of this case-statement and use it in the where part? Is it possible? (Sry this may be a dumb question)
If you define your CASE statement in either an inline-view or a common table expression (aka WITH clause), you can refer to it by whatever alias you give it.
For example (inline-view):
SELECT ...
FROM ( SELECT .....
(CASE
WHEN (Select 1 from DUAL) = 1 THEN 'TEST'
ELSE 'TEST2'
END) AS TEST
FROM...
) v
WHERE v.test = 'TEST2';
As a common table expression, it would be:
WITH cte AS ( SELECT........
(CASE
WHEN (Select 1 from DUAL) = 1 THEN 'TEST'
ELSE 'TEST2'
END) AS TEST
FROM ... )
SELECT ...
FROM cte
WHERE test = 'TEST2';
You can use a case statement in the where clause, for eg.:
select * from table
where table.field = (CASE
WHEN (Select 1 from DUAL) = 1 THEN 'TEST'
ELSE 'TEST2'
END)
This will compare the value returned from the case statement with the table field.

ORACLE: SELECT VALUE IF

I am trying to select different values that depend on different conditions, but I don't exactly know, how one can achieve this in SQL/Oracle..
Here is an example:
SELECT VALUE (I dont exactly know what to write here)
FROM
(SELECT
(CASE
WHEN (Select 1 from DUAL) = 1 THEN 'TEST'
WHEN (Select 1 from DUAL) = 0 THEN 'TEST1'
WHEN (Select 1 from DUAL) = 0 THEN 'TEST2'
ELSE 'N/A'
END)
FROM DUAL);
I want to print different results according to the conditions...For instance, in the example above it should print "TEST"
You need to provide an alias to the CASE statement:
SELECT alias_for_your_case_value
FROM (
SELECT CASE (Select 1 from DUAL)
WHEN 1 THEN 'TEST'
WHEN 0 THEN 'TEST1'
WHEN 0 THEN 'TEST2'
ELSE 'N/A'
END AS alias_for_your_case_value
FROM DUAL
);

Select statement inside CASE - SQL

I am trying to figure out the right code for the below logic. If there is a certain value in the first column, display the value from the second column for that specific record.
Can someone please help? Thanks.
CASE WHEN TableA.Column1 = 'a' THEN 'select TableA.Column2 '
WHEN TableA.Column4 = 'b' THEN 'select TableA.Column5'
ELSE TableA.Column6
END AS [Test]
You were almost there just remove the select from case statement. Since all the values are coming from same table no need of select in case statement just keep column name it will fetch the corresponding column value.
SELECT CASE
WHEN Column1 = 'a' THEN Column2
WHEN Column4 = 'b' THEN Column5
ELSE Column6
END AS [Test]
FROM tableA
Try this:
SELECT (CASE WHEN A.Column1 = 'a' THEN A.Column2
WHEN A.Column4 = 'b' THEN A.Column5
ELSE A.Column6
END) AS [Test]
FROM TableA A;
You are already inside a SELECT, so you do not need an additional SELECT inside:
SELECT
...
, CASE WHEN TableA.Column1 = 'a' THEN TableA.Column2
WHEN TableA.Column4 = 'b' THEN TableA.Column5
ELSE TableA.Column6
END AS [Test]
FROM
TableA
...
You could write it as:
select CASE WHEN TableA.Column1 = 'a' THEN TableA.Column2
WHEN TableA.Column4 = 'b' THEN TableA.Column5
ELSE TableA.Column6
END AS [Test]
from tableA
or even shorter in your case:
select CASE TableA.Column1
WHEN 'a' THEN TableA.Column2
WHEN 'b' THEN TableA.Column5
ELSE TableA.Column6
END AS [Test]
from tableA

Replacing CASE in SQL query

I got three columns with binary values. Then i got a query which makes a string based on those values. I made this work using case. But it's quite huge (it's a part of a bigger query), and i was wondering maybe there is a better way of doing this?
SELECT (CASE
WHEN TableA.flag1 = 1 AND TableA.flag2 = 1 AND TableA.flag3 = 1 THEN 'CGR'
WHEN TableA.flag1 = 1 AND TableA.flag2 = 1 THEN 'CG'
WHEN TableA.flag1 = 1 AND TableA.flag3 = 1 THEN 'CR'
WHEN TableA.flag2 = 1 AND TableA.flag3 = 1 THEN 'GR'
WHEN TableA.flag1 = 1 THEN 'C'
WHEN TableA.flag2 = 1 THEN 'G'
WHEN TableA.flag3 = 1 THEN 'R'
ELSE 'nothing'
END)
FROM TableA
Im working on MSSQL 2000 server.
You can use left() instead.
select left('C', T.flag1)+
left('G', T.flag2)+
left('R', T.flag3)
from TableA as T
I don't know if this is "better" but it is more concise:
SELECT ((CASE WHEN TableA.flag1 = 1 THEN 'C' ELSE '' END) +
(CASE WHEN TableA.flag2 = 1 THEN 'G' ELSE '' END) +
(CASE WHEN TableA.flag3 = 1 THEN 'R' ELSE '' END)
)
FROM TableA;
Okay, this isn't exactly the same because you get '' instead of 'nothing'. But I think the empty string does a better job of representing "no flags" than 'nothing' does.
Try this:
SELECT
CASE WHEN flag1 = 1 THEN 'C' ELSE '' END +
CASE WHEN flag2 = 1 THEN 'G' ELSE '' END +
CASE WHEN flag3 = 1 THEN 'R' ELSE '' END
FROM TABLEA
Maybe you could use function and move this CASE statement to this function