SQL NOT IN function not returning expected result - sql

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.

Related

How to return a null column using NOT IN () in 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')

Not In operator eliminates NULL values rows in a table

I would like to retrieve all rows with values except 1,2,3,4,5 in my COLUMNA in TABLEA .
SELECT * FROM TABLEA WHERE COLUMNA NOT IN (1,2,3,4,5)
But this eliminates the rows with NULL values in COLUMNA too.
I don't want to eliminate NULL values rows and would like to include those rows in the resultset.
Alternatively, I can try below query for the same
SELECT * FROM TABLEA WHERE COLUMNA NOT IN (1,2,3,4,5) OR COLUMNA IS NULL.
But I would like to know, why is it necessary to add this OR condition?
Why is the additional necessary?
NULL comparisons almost always results in NULL, rather than true or false. A WHERE clause filters out all non-true values, so they get filtered out.
This is how SQL defines NULL. Why is NULL defined like this?
NULL does not mean "missing" in SQL. It means "unknown". So, the result of <unknown> not in (1, 2, 3, 4, 5) is "unknown", because the value could be 1 or it might be 0. Hence it gets filtered.
I will also note that the SQL standard includes NULL-safe comparisons, IS NOT DISTINCT FROM and IS DISTINCT FROM corresponding to = and <> respectively. These treat NULL as just "any other value", so two NULL values are considered equal. However, there is no construct for NULL-safe IN and NOT IN, as far as I know.
Try the following:
SELECT * FROM TABLEA WHERE ISNULL(COLUMNA,0) NOT IN (1,2,3,4,5)

Subquery returns more than one row and stops working

I have a table which has got a column. I have to fetch the values from the column and modify it in the view before comparing it with an externally supplied value.
For that I am using the following query:
SELECT COUNT(*)
FROM tblMaster WITH (NOLOCK)
WHERE (SELECT test
FROM
(SELECT RIGHT('00000000000000000' + RTRIM(CODE), 17) as test
FROM tblMaster ) t) = '00001231231231231'
Subquery returns modified values of the column extracted from the actual table in form of a column. So I am using the column returned out of the subquery. I don't know if I can use a subquery which returns a column on the left side of equality.
Subquery returns multiple values.
You don't need a subquery for this:
SELECT COUNT(*)
FROM tblMaster WITH (NOLOCK)
WHERE right('00000000000000000' + RTRIM(CODE), 17) = '00001231231231231';
You can simplify this. You don't need to add 0s to integers, SQL will trim them off when comparing. Also you don't need the subquery:
SELECT COUNT(*)
FROM tblMaster WITH (NOLOCK)
WHERE CODE = '1231231231231'

SQL query to get null count from a column

I want to generate a SQL query to get null count in a particular column like
SELECT COUNT (column) AS count
FROM table
WHERE column = null ;
This is returning 0, but I want how many null values are present in that column like
SELECT COUNT (column) AS count
FROM table
WHERE column = 'some value';
which returns the count of the matched records
NULL value is special in that you cannot use = with it; you must use IS NULL instead:
SELECT COUNT (*) AS count FROM table where column IS null ;
This is because NULL in SQL does not evaluate as equal to anything, including other NULL values. Also note the use of * as the argument of COUNT.
You can use a conditional sum()
SELECT sum(case when column is null
then 1
else 0
end) AS count
FROM table
A different query but exact answer check it out
select count(*)-count(column) from table
please vote check this as answer if it helps you
To get exact output you can use below command as well -
SELECT COUNT (*) AS count FROM table where column IS null OR column='';
because some times only '' doesn't counted as NULL.

Excluding a Null value returns 0 rows in a sub query

I'm trying to clean up some data in SQL server and add a foreign key between the two tables.
I have a large quantity of orphaned rows in one of the tables that I would like to delete. I don't know why the following query would return 0 rows in MS SQL server.
--This Query returns no Rows
select * from tbl_A where ID not in ( select distinct ID from tbl_B
)
When I include IS NOT NULL in the subquery I get the results that I expect.
-- Rows are returned that contain all of the records in tbl_A but Not in tbl_B
select * from tbl_A where ID not in ( select distinct ID from tbl_B
where ID is not null )
The ID column is nullable and does contain null values. IF I run just the subquery I get the exact same results except the first query returns one extra NULL row as expected.
This is the expected behavior of the NOT IN subquery. When a subquery returns a single null value NOT IN will not match any rows.
If you don't exclusively want to do a null check, then you will want to use NOT EXISTS:
select *
from tbl_A A
where not exists (select distinct ID
from tbl_B b
where a.id = b.id)
As to why the NOT IN is causing issues, here are some posts that discuss it:
NOT IN vs. NOT EXISTS vs. LEFT JOIN / IS NULL
NOT EXISTS vs NOT IN
What's the difference between NOT EXISTS vs. NOT IN vs. LEFT JOIN WHERE IS NULL?
Matching on NULL with equals (=) will return NULL or UNKNOWN as opposed to true/false from a logic standpoint. E.g. see http://msdn.microsoft.com/en-us/library/aa196339(v=sql.80).aspx for discussion.
If you want to include finding NULL values in table A where there is no NULL in table B (if B is the "parent" and A is the "child" in the "foreign key" relationship you desire) then you would need a second statement, something like the following. Also I would recommend qualifying the ID field with a table prefix or alias since the field names are the same in both tables. Finally, I would not recommend having NULL values as the key. But in any case:
select * from tbl_A as A where (A.ID not in ( select distinct B.ID from tbl_B as B ))
or (A.ID is NULL and not exists(select * from tbl_B as B where B.ID is null))
The problem is the non-comparability of nulls. If you are asking "not in" and there are nulls in the subquery it cannot say that anything anything is definitely not in becuase it is looking at those nulls as "unknown" and so the answer is always "unknown" in the three value logic that SQL uses.
Now of course that is all assuming you have ANSI_NULLS ON (which is the default) If you turn that off then suddenly NULLS become comparable and it will give you results, and probably the results you expect.
If the ids are never negative, you might consider something like:
select *
from tbl_A
where coalesce(ID, -1) not in ( select distinct coalesce(ID, -1) from tbl_B )
(Or if id is a string, use something line coalesce(id, '<null>')).
This may not work in all cases, but it has the virtue of simplicity on the coding level.
You probably have ANSI NULLs switched off. This compares null values so null=null will return true.
Prefix the first query with
SET ANSI_NULLS ON
GO