Issue with null value using select statement - sql

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.

Related

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.

Count() Specifying Uncounted Value?

Using Microsoft SQL Server, if you use COUNT(column name) it returns the number of rows in that column which have a non-null value (i.e., it counts the rows, ignoring nulls).
Is there any way to do something similar, but allowing you to tell it which values to ignore? For example, if I wanted to count all the rows in a table which have a value which is NOT 1, I could do something like COUNTNOT(column name,1). That would count all the rows in the specified column which have a value NOT 1.
You may use conditional aggregation:
SELECT COUNT(CASE WHEN some_val <> 1 THEN 1 END) AS cnt
FROM yourTable;
The above logic is that COUNT will count one whenever some value is not equal to 1. Otherwise, it falls on the ELSE conditional, which if not present defaults to the value NULL. Since NULL is not counted, any value other than 1 would contribute zero to the count.
Why not put what you want to exclude in a WHERE clause?
SELECT COUNT(some_val) AS cnt
FROM yourTable
WHERE some_val <> 1
You need to be careful about NULL values. I would recommend:
select sum(case when column in (<values to ignore>) then 0 else 1 end)
This will count NULL values as not in the list (even if NULL is in the list). To ignore NULL values (as well), switch the logic to:
select sum(case when column not in (<values to ignore>) then 1 else 0 end)
and be sure NULL is not in the list.

Find certain values and show corresponding value from different field in SQL

So I found these 2 articles but they don't quite answer my question...
Find max value and show corresponding value from different field in SQL server
Find max value and show corresponding value from different field in MS Access
I have a table like this...
ID Type Date
1 Initial 1/5/15
1 Periodic 3/5/15
2 Initial 2/5/15
3 Initial 1/10/15
3 Periodic 3/6/15
4
5 Initial 3/8/15
I need to get all of the ID numbers that are "Periodic" or NULL and corresponding date. So I want a to get query results that looks like this...
ID Type Date
1 Periodic 3/5/15
3 Periodic 3/6/15
4
I've tried
select id, type, date1
from Table1 as t
where type in (select type
from Table1 as t2
where ((t2.type) Is Null) or "" or ("periodic"));
But this doesn't work... From what I've read about NULL you can't compare null values...
Why in SQL NULL can't match with NULL?
So I tried
SELECT id, type, date1
FROM Table1 AS t
WHERE type in (select type
from Table1 as t2
where ((t.Type)<>"Initial"));
But this doesn't give me the ID of 4...
Any suggestions?
Unless I'm missing something, you just want:
select id, type, date1
from Table1 as t
where (t.type Is Null) or (t.type = "") or (t.type = "periodic");
The or applies to boolean expressions, not to values being compared.

CASE statements in Hive

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)

postgres column with nulll values and filtering with "!="

Here is my query:
select * from students where status != 4.
I am not getting rows with status null.
Shouldn't it return all the rows where status is not 4 - including rows with null status values?
I can get what I need by following query.
select * from students where status != 4 or status is null
Use:
IS DISTINCT FROM
SELECT * FROM students WHERE status IS DISTINCT FROM 4;
http://www.postgresql.org/docs/current/interactive/functions-comparison.html
SQL's understanding of NULL is "three-valued". Think of NULL as UNKNOWN. So, in other words:
UNKNOWN = 4 yields UNKNOWN
UNKNOWN != 4 yields also UNKNOWN
In other words, if a student has status is null, then it is "unknown" whether that status is different from 4
This is a bit disturbing but null is not a value and requires its specific operator is.
Any comparison using normal comparison operators with null is never true, except for the two special IS NULL and IS NOT NULL comparisons.