SQL OR within WHEN (in CASE) - mysql

Strangely i could not find this on the web,
I need an OR within a when clause in a case statement, something like:
SELECT type,color,brand,CASE type WHEN "foo" OR "BAR" OR "somethingelse" THEN SELECT ... FROM .... WHERE .... > ....;
I just cant find a way to make it work, i have tried enclosing it in parenthesys:
SELECT type,color,brand,CASE type WHEN ("foo" OR "BAR" OR "somethingelse") THEN SELECT ... FROM .... WHERE .... > ....;
Or in square brackets:
SELECT type,color,brand,CASE type WHEN ["foo" OR "BAR" OR "somethingelse"] THEN SELECT ... FROM .... WHERE .... > ....;
The problem is that i have more groups of options to check, and make a single WHEN for each of them, will make my query super long.
Nothing, any advice?

case has two forms Only one can use Or
case x when val1 then result1 when val2 then result2 else defaultResult end
case when x = val1 then result1 When y = val2 then result2 Else DefaultResult end,
or, more generally:
case when [boolExp1] then reslt1 when [boolExp2] then reslt2 else defltReslt end
the second form can use Or, or any other Boolean operator for that matter (except Exists as I recall)
case when x = val1 or y = val2 or z in (val3, val4, val5) then result1
else defaultResult end

In CASE you cannot start a separate SELECT without brackets ... and the OR is possible with the following:
CASE WHEN type IN ("foo","BAR","somethingelse") THEN ... ELSE END
If you want to get the target value from a select call (subquery) then do this in the THEN section
... THEN ( SELECT col1 FROM tble WHERE ... ) ELSE END

Related

SQL Query on considering a like statement

I am trying to add a column, YES/No, based on text involved. If the Value column contains BALL, we mark it as Yes in the column. But if the 'BALL' is attached with any text/string, it should return it as 'NO'. There are some cases which I have attached
How do I form the case statement so that if any text/string is attached to the 'BALL' without a space should be No, and rest all the cases should be 'Yes'. I tried using like %BALL%, but it does not satisfy all the examples in the above screenshot.
Just insist that the previous and next characters are not letters:
(case when value regexp '([^a-zA-Z]|^)BALL([a-zA-Z]|$)'
then 'YES' else 'NO'
end)
Here is a db<>fiddle.
Set #val variable with value need to lookup:
SET #val := 'BALL';
Run query with two type of checking:
Use LOCATE to find #val value in the table; will return numerical position of the first character of the searched value.
Use SUBSTRING to get two sets of value from string_val column; using the numerical position that was obtained using LOCATE:
val1 will return the value of string_val before the searched value of #val (the LOCATE result need to have a deduction of 1).
val2 will return the value of string_val that matches #val and anything after it.
In the outer query, chk1 checks the last character extracted to val1 against alphabets using REGEXP. In this case GOBALL will return true (1) while 9232BALL and 9232BALLV will return false (0). Here we'll look at whatever false.
chk2 checks if val2 matches the searched #val. Therefore, the separated value of 9232BALL which end up getting BALL for val2 will return true (1) while 9232BALLV which end up getting BALLV for val2 will return false (0). Here we'll look at whatever is true.
The last filter is checking the addition of chk1+chk2. The result we're looking for is 1 because chk1 need to be false (0) and chk2 need to be true (1).
SELECT String_val AS 'Value',
CASE WHEN chk1+chk2=1 THEN 'Yes' ELSE 'No' END AS 'Yes/No'
FROM
(SELECT *,
RIGHT(val1,1) REGEXP '[a-zA-Z]' AS chk1,
val2=#val AS chk2
FROM
(SELECT string_val,
SUBSTRING(string_val,1,LOCATE(#val,string_val)-1) val1,
SUBSTRING(string_val,LOCATE(#val,string_val)) val2
FROM mytable) A) B
Alternative option 1:
SELECT string_val,
CASE WHEN
REGEXP_REPLACE(CASE WHEN val1 REGEXP '[a-zA-Z]$' = 1
THEN CONCAT(val1,val2) ELSE val2 END,'[0-9]','')=#Val
THEN 'Yes' ELSE 'No' END AS 'Yes/No'
FROM
(SELECT string_val,
SUBSTRING(string_val,1,LOCATE(#val,string_val)-1) val1,
SUBSTRING(string_val,LOCATE(#val,string_val)) val2
FROM mytable) A;
Alternative option 2:
My further testing shows that it's possible to get the result using REGEXP_SUBSTR with a much shorter query:
SET #val := 'BALL';
SELECT string_val,
REGEXP_SUBSTR(string_val, '[a-zA-Z]+[BALL]+[a-zA-Z]') AS vals,
IF(((SELECT vals))=#val,'YES','NO') AS 'Yes/No'
FROM mytable;
Demo

How to select the row value based on preference order in the table using MySql

I have table as data_attributes with a column data_type
SELECT * FROM DATA_ATTRIBUTES;
DATA_TYPE
----------
NAME
MOBILE
ETHINICITY
CC_INFO
BANK_INFO
ADDRESS
Bank_info, CC_info classified as Risk1,
Mobile, Ethinicity classified as Risk2,
Name, Address classified as Risk3
I should get the Risk classification as output,
For eg: If any of the row contains Risk1 type then output should be Risk1,
else if any of the row contains Risk2 type then output should be Risk2,
else if any of the row contains Risk3 type then output should be Risk3
I wrote below query for this
SELECT COALESCE(COL1,COL2,COL3) FROM
(SELECT
CASE WHEN DATATYPE IN ('BANK_INFO','CC_INFO') THEN 'RISK1' ELSE NULL END AS COL1,
CASE WHEN DATATYPE IN ('MOBILE','ETHINICITY') THEN 'RISK2' ELSE NULL END AS COL2,
CASE WHEN DATATYPE IN ('NAME','ADDRESS') THEN 'RISK3' ELSE NULL END AS COL3
FROM DEMO.TPA_CLASS1) A;
The required output is: Risk1 ( Only 1 value )
Please give some idea to achieve this.
You can use conditional aggregation:
SELECT
CASE
WHEN MAX(DATATYPE IN ('BANK_INFO','CC_INFO')) = 1 THEN 'RISK1'
WHEN MAX(DATATYPE IN ('MOBILE','ETHINICITY')) = 1 THEN 'RISK2'
WHEN MAX(DATATYPE IN ('NAME','ADDRESS')) = 1 THEN 'RISK3'
END AS RISK
FROM DEMO.TPA_CLASS

I need an SQL query that selects from either Column A or B depending on the existence of a string in Column C

I need an SQL query that selects from Column A if Column C contains the string 'ebook'. Otherwise, select from Column B.
So something like:
IF (Table.ColumnC = "ebook") SELECT Table.ColumnA AS Publisher
ELSE SELECT Table.ColumnB AS Publisher
Select
case when columnC = 'e-book'
then columnA
else columnB
end as Publisher
from myTable;
You need a case statement
I reformatted to help show how this works.
Basically Case is a scalar (row per row) IF statement
There can be multiple conditions WHEN, similar to else if. The function goes from condition to condition, if no conditions are passed, the ELSE value is used.
There are simple and search forms of CASE Documentation
Simple CASE expression:
CASE input_expression
WHEN when_expression THEN result_expression [ ...n ]
[ ELSE else_result_expression ]
END
Searched CASE expression:
CASE
WHEN Boolean_expression THEN result_expression [ ...n ]
[ ELSE else_result_expression ]
END
select case columnC when 'ebook' then columnA else columnB end as publisher
from my_table;
In MySQL you can write it like this:
SELECT IF(Table.ColumnC = 'ebook', Table.ColumnA, Table.ColumnB) AS Publisher FROM Table...
If you have more than one possibility, then go for CASE..WHEN..THEN..ELSE..END.

What's the best way to optimize the case statements?

For example..
I have three case statements, the values of which i want to save it in a variable..
Select
Case when 1 then variable='123' else
case when 2 then variable='456' else
case when 3 then variable='123456'
from
table X where
some conditions ;
try this for example
Select x.field,
Case x.value
when 1 then '123'
when 2 then '456'
when 3 then '123456'
ELSE '789'
END AS variable
from
table X where
some conditions ;

In SQL, is there something like: WHERE x = ANY_VALUE?

In a SQL query like this:
SELECT *
FROM MyTable
WHERE x = 5;
is it possible to modify the WHERE condition so that SELECT looks for every value of x? Something like (wrong syntax):
SELECT *
FROM MyTable
WHERE x = ANY_VALUE;
The reason behind this question is that I have to parse and modify some SQL queries through some C++ code I am writing. I know in this case I could just remove or comment the whole WHERE condition, but this is a simplification.
Thank you.
In cases like this, you normally would do something like this:
SELECT *
FROM MyTable
WHERE x = SOME_VALUE OR 1 = 1;
SOME_VALUE is arbitrary, it can be anything matching the type of the column, because the WHERE clause will always be true because of the second part.
You could just omit WHERE clause. :)
While I think it's really the wrong way to go about it (just make the effort to remove the Where), how about where x = x? It won't work if X is null (you'd have to use "x is null or x = x") but don't bother if you know x won't be null.
You can try that:
SELECT *
FROM MyTable
WHERE x = x OR x IS NULL;
You could make your query like this
DECLARE #VALUE as (type of x)
--SET #VALUE = ''
SELECT *
FROM MyTable
WHERE (#VALUE IS NULL OR x = #VALUE);
and your parse would only have to replace
the: --SET #VALUE = '' line for one with the value you want, minus the comment, like: SET #VALUE = 'abc'
hope this helps