How to return a null column using NOT IN () in SQL - sql

I want to return some data using the following query.
select *
from table
where code_value not in ('44','45','46')
This statement return all expected rows except rows with code_value = null.
I want to get the null columns also.
How can I get that?

Use IS NULL :
WHERE (code_value IS NULL OR code_value not in ('44','45','46'));
NOT IN will not return records when compared against an unknown value or NULL values.

The direct comparison to NULL is the right solution. But I offer this to illustrate the "inverse" of IN. It is more like:
select t.*
from t
except
select t.*
from t
where code_value not in ('44', '45', '46');
Than not in. This is not even exact either, because except removes duplicates. But it is logically closer to the inverse.

I would do it using isnull in conjunction with a default value which doesn't exist in the code_value;
select *
from table
where isnull(code_value,'<<non existing value>>') not in ('44','45','46')

Related

Getting null result when applying not in SQL operator?

I have two tables: opcsourcetags and real_raw_ponts.
There is a foreign key of opcsourcetags in real_raw_points table. I want to get the rows from opcsourcetags against which there is not ID in real_raw_ponits but I am getting the null result. Here is my query:
select *
from OPC_SourceTags opc
where opc.Source_Tag_Id not in (
select rt.Source_Tag_Id_Fk
from Real_Raw_Points rt
)
You should be able to do the following
SELECT opc.* FROM OPC_SourceTags opc
LEFT JOIN Real_Raw_Points rt ON (rt.Source_Tag_Id = opc.Source_Tag_Id)
WHERE rt.Source_Tag_Id is null;
This is because IN/NOT IN uses 3-valued logic. In this case you've used NOT IN, ie NOT TRUE. SQL Server when checking the list of values you supply will evaluate NULL as UNKNOWN, therefore it is unknown whether the source tag id appears in the set.
IN will discard rows it cannot say with certainty are TRUE, whereas NOT IN will return UNKNOWN ie NULL for the entire set, as it cannot say with certainty that the value among the list of values you provided.
I would recommend reading more about 3-valued logic, as it's not a simple thing to explain. You can either use Mukesh's method, but this will not return rows where Source_Tag_Id_Fk is NULL in the Source_Tag_Id_Fk table. Best practice is to use NOT EXISTS instead of NOT IN. NOT EXISTS uses two-valued logic.
select *
from OPC_SourceTags opc
where not exists (
select rt.Source_Tag_Id_Fk
from Real_Raw_Points rt
where opc.Source_Tag_Id = rt.Source_Tag_id_Fk
)
Try below-updated query - Just added where condition in your subquery where rt.Source_Tag_Id_Fk is not null
Note: If there is a null value in this column rt.Source_Tag_Id_Fk the whole result will be null. if there is no null value then your query will also work fine hence you must apply is not null on rt.Source_Tag_Id_fk column in your subquery
select *
from OPC_SourceTags opc
where opc.Source_Tag_Id not in (
select rt.Source_Tag_Id_Fk
from Real_Raw_Points rt where rt.Source_Tag_Id_Fk is not null
)

Null query result cant fetch in Select query in Oracle

I have below query which i am trying to run but not returning the expected result. The ISIN field value which is Null in EXPORT_BB is also getting ignore and not showing the result with the condition given in NOT IN clause. The export_blacklist has only one row value and which is not Null but still i dont for what reason the null value is getting ignored.
Select * from EXPORT_BB where ISIN NOT IN
(
SELECT
ISIN
FROM
export_blacklist);
If i run only select query without the NOT IN clause then i can see values which is NULL for ISIN field.
JUst for test i tried below query and its also resulting nothing. Is it bug in Oracle 18c or something is missing?
select 'null is not in set' from dual where null not in (select 1 from dual);
Any comparison of NULL with =, <>, <, > or in a IN or NOT IN clause will return NULL, so that row is not included in the results (because only rows for which the returned value is TRUE will be included in the results).
Change your code with a condition for the case that ISIN is NULL:
SELECT * FROM EXPORT_BB
WHERE ISIN NOT IN (SELECT ISIN FROM export_blacklist)
OR ISIN IS NULL
NULL values doesn't work with NOT IN it's the normal behaviour.
You have to convert the NULL to another value to be able to operate with it or use IS NULL/IS NOT NULL
Select * from EXPORT_BB where NVL(ISIN, 999999) NOT IN
(
SELECT
NVL(ISIN, 999999)
FROM
export_blacklist);
Comparing to a null value in Oracle always returns false.
Is NULL >= 1? No.
Is NULL < 1? No.
Is NULL in your set? Regardless of what your set is, the answer is no.
Is NULL not in your set? Again, no.
It is the expected behaviour. NOt related to 18c it is the same way from Oracle 7 onwards
NOT IN doesnt consider nulls.
NOT EXISTS does consider nulls.
Consider the following example in db fiddle
https://dbfiddle.uk/?rdbms=oracle_18&fiddle=8be0a790d8172093a032602345038e8e
See a discussion on this
https://asktom.oracle.com/pls/apex/asktom.search?tag=in-vs-exists-and-not-in-vs-not-exists
As you have been answered by collegues you have to specify that you wanna return null values too.
Namely
SELECT *
FROM EXPORT_BB
WHERE ISIN NOT IN (SELECT ISIN FROM EXPORT_BLACKLIST)
OR ISIN IS NULL;

SQL NOT IN function not returning expected result

Total number of records in table i1450:
Total number with condition where i.BROJ is equal to field REFERENCA in other table:
Shouldn't it return difference between last two results (which is 64) when I use NOT IN in WHERE clause?
Both of columns are of varchar type.
If you have any NULL values in the REFERENCA column from the FpsPmtOrderRQ table then the NOT IN clause will not work as expected - (the reason why)
A solution is to remove NULL values from the result returned by the subselect.
SELECT COUNT(*)
FROM i1450 j
WHERE i.BROJ NOT IN (SELECT REFERENCA FROM FpsPmtOrderRQ WHERE REFERENCA IS NOT NULL)
If the sub-query returns a null value, the IN will not be true. Do NOT EXISTS instead.
select count(*)
from i1450 i
where not exists (select 1 from FpsPmtOrderRQ f
where i.broj = f.REFERENCA)
I think you need to coalesce your field to handle nulls. That is probably why you get 0.
By doing:
where coalesce(I.BROJ,'n/a') not in (select coalesce(REFERENCA,'')
or something similar, you would exclude nulls, and return a proper count.

Oracle Coalesce returns blank

I have following query which uses coalesce to return the id of a calendar with a specific code
SELECT COALESCE(SD_CALENDAR.ID,0) FROM SD_CALENDAR WHERE SD_CALENDAR.CODE = 'BOER';
But when I run this I get a blank column as result, instead of 0. What do I need to change to make my query work?
You said that no rows in your table match your query, so you are trying to return 0 when there is no match, rather than returning no data at all.
If NAME is unique then you could use an aggregate to achieve this:
SELECT COALESCE(MAX(SD_CALENDAR.ID),0) FROM SD_CALENDAR WHERE SD_CALENDAR.CODE = 'BOER';
The MAX() will always return one row; if there is a match it will be the single ID anyway, and if there isn't it will be null - which you can then coalesce to zero.
If NAME isn't unique and you expect multiple values back then you can use a union to provide the zero value when there is no match:
SELECT COALESCE(SD_CALENDAR.ID,0) FROM SD_CALENDAR WHERE SD_CALENDAR.CODE = 'BOER'
UNION ALL
SELECT 0 FROM DUAL WHERE NOT EXISTS (
SELECT COALESCE(SD_CALENDAR.ID,0) FROM SD_CALENDAR WHERE SD_CALENDAR.CODE = 'BOER'
);
Depending on what you're doing, it might be better/easier to let your application handle a no-data-found result and substitute a zero itself.

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.