Not in clause on a column with Null values - sql

I have a table with 10 odd columns, one of them being 'Status'.
I wanted to fetch all rows where Status is not Rejected, so I wrote the following query on Hive:
select * from table1 where status <> 'Rejected'
However Hive is not returning me rows where the Status was Null. I changed the query to
select * from table1 where status <> 'Rejected' or status is Null
But I can't find any documentation to understand why this is happening.
Can someone please help me with this?

Hive implements the NULL-safe comparison operator. So you can do:
select *
from table1
where not status <=> 'Rejected' ;
As for your question, it is a pretty basic question on what NULL means in databases. It doesn't mean "missing", it means "unknown". Almost all comparison operations return NULL when either operand is NULL -- the exceptions are operands (such as <=>, is not null and is null) that are specific designed to handle NULL values.

null isn't a value, it's the lack thereof. Whenever you try to use it in a context of the value, the result would be "unkonwn". You can think about it like this - "is an unknown (=null) value different from 'Rejected'? We don't know."
Thus, you need to specifically handle it with the is [not] operator. You can think of the second where clause you shared as "all the statuses that are not known to have the value 'Rejected'".

Related

CASE SQL statement oracle database

my requirement is if first condition is null then check for the second condition if second condition is null as well then third condition in oracle database, so I am trying to achieve this by case statement as shown below but getting an error as missing expression/missing keyword.
CASE
WHEN (TRUNC( OTA_EVENTS.COURSE_START_DATE) BETWEEN PER_ALL_ASSIGNMENTS_F.EFFECTIVE_START_DATE AND PER_ALL_ASSIGNMENTS_F.EFFECTIVE_END_DATE ) IS NULL
then (TRUNC(OTA_DELEGATE_BOOKINGS.Date_Booking_Placed) BETWEEN PER_ALL_ASSIGNMENTS_F.EFFECTIVE_START_DATE AND PER_ALL_ASSIGNMENTS_F.EFFECTIVE_END_DATE)
ELSE (TRUNC(OTA_DELEGATE_BOOKINGS.DATE_STATUS_CHANGED) BETWEEN PER_ALL_ASSIGNMENTS_F.EFFECTIVE_START_DATE AND PER_ALL_ASSIGNMENTS_F.EFFECTIVE_END_DATE)
END
Please help if there is any other way to achieve this
my requirement is if first condition is null then check for the second condition if second condition is null as well then third condition in oracle database
I don't see what your code has to do with this question (it is using between rather than NULL comparison. ABut what you are describing is COALESCE():
select coalesce(a, b, c)
This can take as many arguments as you need. It returns the first non-NULL value.
It means you need OR between your conditions:
(TRUNC(OTA_EVENTS.COURSE_START_DATE)
BETWEEN PER_ALL_ASSIGNMENTS_F.EFFECTIVE_START_DATE
AND PER_ALL_ASSIGNMENTS_F.EFFECTIVE_END_DATE
OR ( TRUNC(OTA_DELEGATE_BOOKINGS.DATE_BOOKING_PLACED)
BETWEEN PER_ALL_ASSIGNMENTS_F.EFFECTIVE_START_DATE
AND PER_ALL_ASSIGNMENTS_F.EFFECTIVE_END_DATE )
OR ( TRUNC(OTA_DELEGATE_BOOKINGS.DATE_STATUS_CHANGED)
BETWEEN PER_ALL_ASSIGNMENTS_F.EFFECTIVE_START_DATE
AND PER_ALL_ASSIGNMENTS_F.EFFECTIVE_END_DATE ))

Can a WHERE clause predicate evaluate to NULL?

Can a WHERE clause return NULL instead of TRUE or FALSE?
According to the exercise below it is possible, but i can't imagine an example that returns NULL, Is it really possible?
4. Which of the following values can NOT be returned after evaluation of WHERE clause
condition?
A. UNKNOWN
B. TRUE
C. FALSE
D. NULL
Answer: A. If the result of the condition in WHERE clause is not known, NULL is returned. In all
other scenarios, either TRUE or FALSE is returned.
In SQL, all logical operators evaluate to TRUE, FALSE, and UNKNOWN (Oracle docs) in MySQL UNKNOWN result calls NULL (MySQL docs).
According to oracle documentation:
"To test for nulls, use only the comparison conditions IS NULL and IS
NOT NULL. If you use any other condition with nulls and the result
depends on the value of the null, then the result is UNKNOWN."
So only TRUE, FALSE, and UNKNOWN can be returned after evaluation.
About your question:
"Can a WHERE clause return NULL instead of TRUE or FALSE?"
Strictly speaking in Oracle - NO because the such result called UNKNOWN.
But in general the meaning of UNKNOWN and NULL is equivalent in this context and it is just a different name for the same thing.
So the example of SQL below (a.a >= all) evaluated as UNKNOWN.
with table_a as (
select null as a from dual
union all
select 10 as a from dual
union all
select 5 as a from dual),
table_b as (
select null as a from dual
union all
select 10 as a from dual
union all
select 5 as a from dual)
select * from table_a a where a.a >= all(select a from table_b b)
As to explain the reason, consider that the SQL language uses a three-value logic: TRUE, FALSE, and NULL. Let's consider this Orders table,
If we run the following query it wont return rows for CPU and Monitor
SELECT * FROM Orders WHERE (qty < 1000 Or qty >= 1000)
In this case, for CPU and Monitor condition (qty < 1000 Or qty >= 1000)returns neither TRUE nor FALSE. It returns NULL. Because logically it is unknown. So, the result of the condition in WHERE clause is unknown and it returned NULL.
You can consider this reference.
Not even a NULL can be equal to NULL.
The correct way to understand NULL is that it is not a value. Not
“this is a NULL value” but “this NULL is not a value.” Everything
either is a value, or it isn’t.
When something is a value, it is “1,” or “hello,” or “green,” or
“$5.00″ etc – but when something isn’t a value, it just isn’t
anything at all.
SQL represents “this has no value” by the special non-value NULL.
When someone says “the NULL value,” one should mentally disagree,
because there’s no such thing. NULL is the complete, total absence
of any value whatsoever.
emphasized text
A Non-Technical aspect
If you ask two girls, how old they are? may be you would hear them to
refuse to answer your question, Both girls are giving you NULL as age
and this doesn't mean both have similar age. So there is nothing can
be equal to null.
SELECT 0 IS NULL , 0 IS NOT NULL , '' IS NULL , '' IS NOT NULL, NULL != NULL, NULL = NULL, NULL != '', NULL = ''

Checking tables for null returns 0 regardless

I don't understand why this query doesn't work.
I have a table which is full of rows where 3 of the column values are set to NULL.
But when I run the following query, it returns 0 (it should return 96)
SELECT COUNT(*) FROM SEAT WHERE BOOKED=null;
Do you know what I am doing wrong?
It depends on your database settings and the specific RDBMS you are using, but if you are using ANSI NULL syntax you cannot directly compare a value to NULL with an equality test (=) -- it will always fail.
Use WHERE BOOKED IS NULL instead.
You have to use IS NULL instead of = null
Since null technically isn't a value, you can't compare null using the = operator.
Use IS NULL
SELECT COUNT(*)
FROM SEAT
WHERE BOOKED IS NULL

mismatch not picked up when one value is null

I have a simple SQL query where a comparison is done between two tables for mismatching value.
Yesterday, we picked up an issue where one field was null and the other wasn't, but a mismatch was not detected.
As far as I can determine,the logic has been working all along until yesterday.
Here is the logic of the SQL:
CREATE TABLE Table1
(UserID INT,PlayDate DATETIME)
CREATE TABLE Table2
(UserID INT,PlayDate DATETIME)
INSERT INTO Table1 (UserID)
SELECT 5346
INSERT INTO Table2 (UserID,PlayDate)
SELECT 5346,'2012-11-01'
SELECT a.UserID
FROM Table1 a
INNER JOIN
Table2 b
ON a.UserID = b.UserID
WHERE a.PlayDate <> b.PlayDate
No values are returned even though the PlayDate values are different.
I have now updated the WHERE to read:
WHERE ISNULL(a.PlayDate,'') <> ISNULL(b.PlayDate,'')
Is there a setting in SQL which someone could have changed to cause the original code to no longer pick up the difference in fields?
Thanks
NULL <> anything
is unknown not true. SQL uses three valued logic (false/true/unknown) and the predicate needs to evaluate to true in a where clause for the row to be returned.
In fact in standard SQL any comparison with NULL except for IS [NOT] NULL yields unknown. Including WHERE NULL = NULL
You don't state RDBMS but if it supports IS DISTINCT FROM you could use that or if you are using MySQL it has a null safe equality operator <=> you could negate.
You say you think it previously behaved differently. If you are on SQL Server you might be using a different setting for ANSI_NULLS somehow but this setting is deprecated and you should rewrite any code that depends on it anyway.
You can simulate IS DISTINCT FROM in SQL Server with WHERE EXISTS (SELECT a.PlayDate EXCEPT SELECT b.PlayDate)
Not even a NULL can be equal to NULL.
Here are two common queries that just don’t work:
select * from table where column = null;
select * from table where column <> null;
there is no concept of equality or inequality, greater than or less
than with NULLs. Instead, one can only say “is” or “is not”
(without the word “equal”) when discussing NULLs.
- The correct way to write the queries
select * from table where column IS NULL;
select * from table where column IS NOT NULL;

Can Anyone explain why NULL is used in this query?

Also what will be the scenarios where this query is used
select * from TableA where exists
(select null from TableB where TableB.Col1=TableA.Col1)
As the query is in an EXISTS then you can return anything. It is not even evaluated.
In fact, you can replace the null with (1/0) and it will not even produce a divide by zero error.
The NULL makes no sense. It's simply bad SQL.
The exists clause is supposed to use SELECT *.
People make up stories about the cost of SELECT *. They claim it does an "extra" metadata query. It doesn't. They claim it's a "macro expansion" and requires lots of extra parse time. It doesn't.
The EXISTS condition is considered "to be met" if the subquery returns at least one row.
The syntax for the EXISTS condition is:
SELECT columns
FROM tables
WHERE EXISTS ( subquery );
Please note that "Select Null from mytable" will return number of rows in mytable but all will contain only one column with null in the cell as the requirement of outer query is just to check whether any row fall in the given given condition like in your case it is "TableB.Col1=TableA.Col1"
you can change null to 1, 0 or any column name available in the table. 1/0 may not be a good idea :)
It's a tacky way of selecting all records in TableA, which have a matching record (Col1=Col1) in TableB. They might equally well have selected '1', or '*', for instance.
A more human-readable way of achieving the same would be
SELECT * FROM TableA WHERE Col1 IN ( SELECT Col1 IN TableB )
Please, please, all ....
EXISTS returns a BOOLEAN i.e. TRUE or FALSE. If the result set is non empty then return TRUE. Correlation of the sub-query is important as in the case above.
i.e Give me all the rows in A where AT LEAST one col1 exists in B.
It does not matter what is in the select list. Its just a matter of style.