CASE statements in Hive - sql

Ok, i have a following code to mark records that have highest month_cd in tabl with binary flag:
Select t1.month_cd, t2.max_month_cd
,CASE WHEN t2.max_month_cd != null then 0 else 1 end test_1
,CASE WHEN t2.max_month_cd = null then 0 else 1 end test_2
from source t1
Left join (
Select
MAX(month_cd) as max_month_cd
From source
) t2
on t1.month_cd = t2.max_month_cd;
It seems straight forward to me, but result it return is:
month_cd max_month_cd test_1 test_2
201610 null 1 1
201611 201611 1 1
Makes zero sense to me, and seems to be way too obvious to be a bug in execution engine. What am i missing?

This is all about NULL concept.
Since Null is not a member of any data domain, it is not considered a "value", but rather a marker indicating the absence of value. Because of this, comparisons with Null can never result in either True or False, but always in a third logical result, Unknown. NULL is nothing, absence of object. So, nothing can NOT be equal to NULL or something else. In SQL there are IS NULL and IS NOT NULL conditions to be used for test for null values.
In your CASE the result of logical expression is unknown, so ELSE value is assigned.
Corrected version:
CASE WHEN t2.max_month_cd IS NOT null then 0 else 1 end test_1,
CASE WHEN t2.max_month_cd IS null then 0 else 1 end test_2
See this for reference: Null (SQL)

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.

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"

Counting how many data that exist [SQL]

im not sure about this question is already asked by anyone else or not yet because this is actually easy but my head is just still can't see the way out of this problem.
this is just like how many times that we do sampling at the material.
SELECT
TABLE01.MATERIAL_NO,
TABLE01.Sample_Tempt1,
TABLE01.Sample_Tempt2,
TABLE01.Sample_Tempt3,
TABLE01.Sample_Tempt4,
TABLE01.Sample_Tempt5
FROM
TABLE01
is it possible to create another column to show count of sample_tempt times?
i mean, if the tempt1 tempt2 data are exist, the column shows 2, when tempt2, tempt4 and tempt5 data are exist, the column show 3. and so on.
Thank you for helping me ^^
Sample :
Material no | Sample_Tempt1 | Sample_Tempt2 | Sample_Tempt3 | Sample_Tempt4 | Sample_Tempt5 |
PO1025 120 150 102
PO1026 122
For the PO1025, i want to create new column that generate "3" because the sample data that exist is only 3, for the PO1026 i want it generate "1" since the sample data that exist is only "1". quite simple right?
If "by exist" you mean "value is not NULL", then you can count the number of non-NULL values in each row as:
SELECT t1.MATERIAL_NO,
t1.Sample_Tempt1, t1.Sample_Tempt2, t1.Sample_Tempt3, t1.Sample_Tempt4, t1.Sample_Tempt5,
((case when t1.sample_temp1 is not null then 1 else 0 end) +
(case when t1.sample_temp2 is not null then 1 else 0 end) +
(case when t1.sample_temp3 is not null then 1 else 0 end) +
(case when t1.sample_temp4 is not null then 1 else 0 end) +
(case when t1.sample_temp5 is not null then 1 else 0 end)
) as NumTempts
FROM TABLE01 t1;
Note that I introduced a table alias. This makes the query easier to write and to read.

Issue with null value using select statement

I am trying to use this select statement but my issue is for this ID that i am trying to use in my select statement has null value. Even though ID 542 has null value but i know for fact in the future is going to have a 'COMPLETE' value in it. The 3 possible values for the FLAG field are COMPLETE, NOT COMPLETE AND NULL. What i want to achieve with this select statement is to see all records where FLAG is not 'COMPLETE'. If i run my query now, it will not return anything but if i remove FLAG <>'COMPLETE' then it will return the record ID 542 but the flag value is null.
Here is my code
SELECT ID, DT, STAT FROM myTable WHERE ID = 542 and FLAG <> 'COMPLETE'
Convert the NULL to text:
SELECT ID, DT, STAT
FROM myTable
WHERE ID = 542 and ISNULL(FLAG,'NULL') <> 'COMPLETE'
SELECT ID, DT, STAT
FROM myTable
WHERE ID = 542 and ISNULL(FLAG, 'NOT COMPLETE') <> 'COMPLETE'
Since the FLAG is null it cannot be compared against 'COMPLETE' and you're missing the entry...
or:
SELECT ID, DT, STAT
FROM myTable
WHERE ID = 542 AND (FLAG <> 'COMPLETE' OR FLAG IS NULL)
Welcome to SQL's three valued logic! The well-known brothers true and false have a secret stepsister called unknown. And the result of a comparison with null is always unknown.
A quick fix is to add an explicit is null check:
where Flag is null or Flag <> 'COMPLETE'
Note that not unknown is still unknown, so this won't work:
where not Flag = 'COMPLETE' -- Won't work
In fact, not even null is equal to null. But null isn't not equal to null either!
For more fun, have a look at Wikipedia. It has a whole page dedicated to three valued logic in SQL.