CASE WHEN comparison resolved to NULL - sql

What's the best way to write this?
I'm running through a couple of scenarios with a CASE WHEN statement. When matched on both and school then return 1. If there is no match, then match on name and school = NULL and return 2. If still no match then return 0.
ie:
CASE WHEN (x.name = x.name and x.school = y.school) THEN 1
WHEN (x.name = x.name and x.school = compare and resolve to null if not matched) THEN 2
ELSE 0
Problem 1: How to write line 2. -- I think I have this resolved.
CASE WHEN (x.name = x.name and x.school = y.school) THEN 1
WHEN (x.name = x.name and y.school is null) THEN 2
ELSE 0
Problem 2: Once I figure out how to write the comparison for line 2, the true resolve of branch 2 will need to pick the lowest tier of the 2 null school values. In the image below, say there is no match on name and school, so the logic moves on to branch 2 comparing (name and school is null). In this case, there are two possibilities for the combination - tier 2 and tier 3.
How do I write a THEN argument to pick the lowest tier of the twe for branch 2?

Is this what you want?
case
when x.name = y.name and x.school = y.school then 1
when x.name = y.name and x.school is null and y.school is null then 2
else 0
end
The first branch succeeds if both name and school match. The second matches on names that are equal and both schools having null values.

Related

Using case statement to compare columns

I'd like to use a case statement to compare multiple rows on 2 columns. For example, if row 1 column 1 and row 2 column 1 match but row 1 column 2 and row 2 column 2 don't, then xx. I have
CASE
WHEN (pprof.description = pprof.description and PCtrl.[sequence] <> PCtrl.[sequence])
THEN xx
but that doesn't return any values, which I know to be incorrect. I'm new to SQL so apologies if I've got this all wrong.
Edit:
Here's some sample data:
Column 1
Column 2
Column 3
123
-A
-No
123
-B
-Yes
Can't figure out the formatting here but there are 3 columns of data above. I'd like the case statement to evaluate whether column 1 match in 2 different rows (i.e., 123 = 123) and also whether column 2 doesn't (A <> B) and if both those conditions are true, return a value in column 3 (in my case, make the No a Yes, since 123-B is Yes). It might be worth noting that the "Yes" and "No" themselves are built into the larger case statement here:
(CASE WHEN tenure.description not in ('casual','co-op','fswep') THEN CASE WHEN (pprof.description = pprof.description and PCtrl.[sequence] <> PCtrl.[sequence])
THEN CASE WHEN (PEmp.Employee_Number = PEmp3.Supervisor_Number) THEN 'Yes' ELSE 'No' END END END) as 'People Manager'
You will want to do a self join here. Without seeing your data, I can't really give you an answer, but you want something like this.
Update A
Set column_3 = 'YES' /* or put CASE statement here /*
FROM pprof A
INNER JOIN pprof B
ON a.description = b.description
AND a.sequence != b.sequence
You may need more join conditions depending on the form of your data and what you want.

How can I make IF without ELSE on SQL WHERE condition?

I`m trying to make a querie that selects users and if user type equals 1 I need to select those with age. My table:
id (int 11) | type (int 11) | email (varchar 25) | age (int 11)
My querie:
SELECT * FROM users WHERE IF(type = 1, age <> 0)
The problem is that I need to have an ELSE condition, but I dont need one in this case. How can I make an IF inside WHERE without else condition?
Thanks
You can do it with CASE:
SELECT * FROM users
WHERE age = CASE WHEN type <> 1 THEN age ELSE 0 END
Q: How do I make IF without ELSE on SQL WHERE condition ?
A: It's not possible; there is always an ELSE. MySQL IF() function has three arguments. It doesn't matter where the IF() function is used, whether it's part of an expression in a WHERE clause, or an expression in the SELECT list.
As an alternative to the MySQL IF() function, we can use a more portable, more ANSI-standard compliant CASE expression. But that doesn't get away from the crux of the question, about avoiding an ELSE. There is always an ELSE with the CASE expression as well. If we omit the ELSE clause, it's the same as if we had specified ELSE NULL.
As an aside (unrelated to the question that was asked), I don't think we should be storing age as an attribute; typically age is the difference between the current date and a date in the past (date of birth, registration date, etc.)
I'm thinking we don't need an IF function in the WHERE clause. (That's specific to MySQL, so this answer assumes that the target DBMS is MySQL, and not some other RDBMS).
We can use a combination of conditions, combined with NOT, AND, OR and parens so specify an order of operations.
Sample data and example output goes a long way to explaining the spec.
id type age email
-- ---- ---- ----------
1 0 0 1#one
2 1 0 2#two
3 0 1 3#three
4 1 1 4#four
5 0 NULL 5#five
6 1 NULL 6#six
7 NULL NULL 7#seven
8 NULL 0 8#eight
9 NULL 1 9#nine
Which of these rows should be returned, and which rows should be excluded?
Here is an example query (MySQL specific syntax) that returns all rows except row id=2 (type=1, age=0)
SELECT u.id
, u.type
, u.age
, u.email
FROM user u
WHERE NOT ( u.type <=> 1 )
OR NOT ( u.age <=> 0 )
If there's a requirement to incorporate IF functions, we can do that, and return an equivalent result:
SELECT u.id
, u.type
, u.age
, u.email
FROM user u
WHERE NOT ( IF( u.type <=> 1 ,1,0) )
OR NOT ( IF( u.age <=> 0 ,1,0) )
^^^ ^^^^^
In the WHERE clause, an expression will be evaluated as a boolean value. A numeric value of 0 is FALSE, a non-zero value is TRUE, and NULL value is (as always) just NULL.
For a row to be returned, we need the expression in the WHERE clause to evaluate to a non-zero value (to evaluate to TRUE).
The third argument of the IF() function is the "else" value; for that value, we can return TRUE, FALSE or NULL. To exclude rows that do not satisfy the type=1 condition, we return either zero or NULL:
WHERE IF(type = 1, age <> 0 ,0 )
^^
or equivalently:
WHERE IF(type = 1, age <> 0 ,NULL )
^^^^^
If we want rows that don't satisfy type=1 condition to be returned, we can return any non-zero value:
WHERE IF(type = 1, age <> 0 ,42 )
^^^
RECAP:
Addressing the question that was asked:
Q: How do I make IF without ELSE on SQL WHERE condition ?
A: There is always an ELSE value with the MySQL IF() function; in the context of the WHERE clause, the value will be evaluated as a boolean: TRUE, FALSE or NULL.
I think you want:
SELECT *
FROM users
WHERE type <> 1 OR age <> 0;
I was in a similar situation and ended up with the following solution:
SELECT * FROM users WHERE IF(type = 1, age <> 0, 1=0)
The else part here is 1 = 0 which is never true, so you don't select anything in that case.

Update a column based on its current value

Is there any way to change field value based on its current value with one query?
Like I have tbl.team and if it's value = 1, change it to 2. And vice versa, tbl.team = 2 => 1.
You can use a case expression to update the column conditionally:
update the_table
set team = case
when team = 1 then 2
else 1
end
where team in (1,2);

Can a CASE expression have 2 resultant values

I have to write a case expression in SQL which goes like this,
case condition
if (T_CD = 'Y')
Case C_CD = 'H3'
set R_ID = 3 and RS_ID = 25
CASE A_FLG = 'N' and Mod = 'D'
set R_ID = 3 and RS_ID = 31
Both R_ID and RS_ID populate columns in a different table and have to be derived as per condition above.
My question is - Since I want 2 separate fields out of my case expression, will a single Case give out 2 resultant field values for me. Or Do I have to write 2 different case expressions for it.
If your dbms supports row types, maybe this works for you:
select case when a = 1 then (1,2) else (3,4) end from testtable;
The SQL Validator says:
The following feature outside Core SQL-2003 is used:
T051, "Row types"

case compare to number and give out name

the problem I have is that I have a column called cate with the numbers 1 to 5 but I want alias names in the print out.
For example if the column has the number 1 I want STONE in the result set, if it is 2 I want "TREE".
I should look something like
Select
case when t.cate = 1 then t.cate="STONE"
case when t.cate = 2 then t.cate="TREE"
else null end as test from dbt.tbl t
I do not want to change the value in the table only in the print out.
Any idea how I can that to work?
Thanks for all your help in advance
remove extra case,
SELECT CASE WHEN t.cate = 1 THEN 'STONE'
WHEN t.cate = 2 THEN 'TREE'
ELSE null
END AS test
FROM dbt.tbl t
Alternatively, you can write
SELECT
CASE t.cate
WHEN 1 THEN 'STONE'
WHEN 2 THEN 'TREE'
ELSE NULL
END AS test
FROM dbt.tbl t
If the list is likely to change in the future (either through edits or additions), I'd do it as a separate table:
INSERT INTO Cates (Cate,Description) VALUES
(1,'Stone'),
(2,'Tree') --Etc
And then just do:
SELECT c.Description as Test
FROM dbt.tbl t inner join Cates c on t.Cate = c.Cate