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)
Consider a table with two nullable columns a and b of any type, and some other arbitrary columns.
I can count cases where one column is not null with:
select count(a) from ...
I can count cases where either column is not null with:
select count(coalesce(a, b)) from ...
But the only way I've been able to figure out how to count cases where both columns are not null is the rather clunky:
select sum(iif(a is not null and b is not null, 1, 0)) from ...
Is there a more concise way to count if both are not null? If there's no general way, is there a way if both columns are int, or if both columns are nvarchar?
The reason I don't want to do it in a where clause, e.g.:
select count(*) from ... where a is not null and b is not null
Is that I'm selecting multiple counts from the same subquery at once:
select count(*)
,count(a)
,count(b)
,sum(iif(a is not null and b is not null, 1, 0))
from ...
And the other reason it needs to take this form is too long to explain here but basically boils down to this being part of a rather complicated query with a very specific structure related to performance.
This question is more out of curiosity, as sum(iif(...)) does work, I'm just wondering if there is something as concise as coalesce(a, b) for the and case.
This is SQL Server 2016, SP1.
In a special case, if both columns are nvarchar,
you could try
COUNT(a + b)
If data type is interger, then use
Count(a/2 + b/2)
To avoid overflow error.
Note: a+b is not null only when both a and b are not null
As #JasonC's suggestion, I add another solution for bitwise operators type:
Count(a & b)
A CASE statement should work well here:
SELECT CASE
WHEN a IS NULL OR b IS NULL
THEN 0
ELSE 1
END
FROM ...
I have 2 tables (stud and stud1). Both having 2 columns but stud1 contains 1 record which is null.
I have created following 2 queries.First one is returning the accurate result but other one which is using not in returning nothing. I guess that is because of the null value. But I don't understand the reason for it. Can someone help me with this?
See NOT IN clause and NULL values.
That's because your 2nd query equals:
SELECT * FROM #stud
WHERE ID <> NULL
When ansi_nulls is on, ID <> NULL is unknown, so you won't get any rows.
SELECT *
FROM REVIEW
WHERE REVIEWERID =5 AND APPRAISEECONFIRMYN='Y' AND HRCONFIRMYN = NULL
Are 2 'AND' conditions allowed like this? I'm not getting the correct output. There are 2 records in the database that fulfil the above conditions. When I remove the last condition 'HRCONFIRMYN = NULL' and execute, I get the correct output.
How can this be solved? I need to check all 3 conditions whilst searchng the records.
To compare the NULL values, you have to use the IS NULL predicate instead of = NULL like so:
SELECT *
FROM REVIEW
WHERE REVIEWERID = 5
AND APPRAISEECONFIRMYN = 'Y'
AND HRCONFIRMYN IS NULL
use OR instead
group your condition
use IS NULL when comparing with NULLs
query,
SELECT *
FROM REVIEW
WHERE (REVIEWERID =5 AND APPRAISEECONFIRMYN='Y') OR
HRCONFIRMYN IS NULL
Good morning,
In a query I was writing yesterday between two decent-sized result sets (<50k results each), part of my JOIN was a clause to check if the data matched or was null (simplified version below):
SELECT a JOIN b ON a.class = b.class OR (a.class is null AND b.class is null)
However, I noticed a serious performance issue centered around the use of the OR statement. I worked around the issue using the following:
SELECT a JOIN b ON NVL(a.class, 'N/A') = NVL(b.class, 'N/A')
The first query has an unacceptably long run time, while the second is a couple of orders of magnitude faster (>45 minutes vs. <1). I would expect the OR to run slower due to more comparisons, but the cases in which a.class = b.class = null are comparatively few in this particular dataset.
What would cause such a dramatic increase in performance time? Does Oracle SQL not short-circuit boolean comparisons like many other languages? Is there a way to salvage the first query over the second (for use in general SQL not just Oracle)?
You're returning a cross product with any record with a null class. Is this OK for your results?
I created two sample query in 11gR2:
WITH a as
(select NULL as class, 5 as columna from dual
UNION
select NULL as class, 7 as columna from dual
UNION
select NULL as class, 9 as columna from dual
UNION
select 'X' as class, 3 as columna from dual
UNION
select 'Y' as class, 2 as columna from dual),
b as
(select NULL as class, 2 as columnb from dual
UNION
select NULL as class, 15 as columnb from dual
UNION
select NULL as class, 5 as columnb from dual
UNION
select 'X' as class, 7 as columnb from dual
UNION
select 'Y' as class, 9 as columnb from dual)
SELECT * from a JOIN b ON (a.class = b.class
OR (a.class is null AND b.class is null))
When I run EXPLAIN PLAN on this query, it indicates the tables (inline views in my case) are joined via NESTED LOOPS. NESTED LOOPS joins operate by scanning the first row of one table, then scanning each row of the other table for matches, then scanning the second row of the first table, looks for matches on the second table, etc. Because you are not directly comparing either table in the OR portion of your JOIN, the optimizer must use NESTED LOOPS.
Behind the scenes it may look something like:
Get Table A, row 1. If class is null, include this row from Table A on the result set.
While still on Table A Row 1, Search table B for all rows where class is null.
Perform a cross product on Table A Row 1 and all rows found in Table B
Include these rows in the result set
Get Table A, row 2. If class is null, include this row from Table A on the result set.
.... etc
When I change the SELECT statement to SELECT * FROM a JOIN b ON NVL(a.class, 'N/A') = NVL(b.class, 'N/A'), EXPLAIN indicates that a HASH JOIN is used. A hash join essentially generates a hash of each join key of the smaller table, and then scans the large table, finding the hash in the smaller table for each row that matches. In this case, since it's a simple Equijoin, the optimizer can hash each row of the driving table without problems.
Behind the scenes it may look something like:
Go through table A, converting NULL class values to 'N/A'
Hash each row of table A as you go.
Hash Table A is now in temp space or memory.
Scan table B, converting NULL class values to 'N/A', then computing hash of value. Lookup hash in hash table, if it exists, include the joined row from Table A and B in the result set.
Continue scanning B.
If you run an EXPLAIN PLAN on your queries, you probably will find similar results.
Even though the end result is the same, since you aren't joining the tables in the first query with "OR", the optimizer can't use a better join methodology. NESTED LOOPS can be very slow if the driving table is large or if you are forcing a full table scan against a large secondary table.
You can use the ANSI COALESCE function to emulate the NVL oracle function in other database systems. The real issue here is that you're attempting to join on a NULL value, where you really should have a "NO CLASS" or some other method of identifying a "null" class in the sense of null = nothing instead of null = unknown.
Addendum to answer your question in the comments:
For the null query the SQL engine will do the following:
Read Row 1 from Table A, class is null, convert to 'N/A'.
Table B has 3 Rows which have class is null, convert each null to 'N/A'.
Since the first row matches to all 3 rows, 3 rows are added to our result set, one for A1B1, A1B2, A1B3.
Read Row 2 From Table A, class is null, convert to 'N/A'/
Table B has 3 Rows which have class is null, convert each null to 'N/A'.
Since the second row matches to all 3 rows, 3 rows are added to our result set, one for A2B1, A2B2, A2B3.
Read Row 3 From Table A, class is null, convert to 'N/A'/
Table B has 3 Rows which have class is null, convert each null to 'N/A'.
Since the third row matches to all 3 rows, 3 rows are added to our result set, one for A3B1, A3B2, A3B3.
10.. Rows 4 and 5 aren't null so they won't be processed in this portion of the join.
For the 'N/A' query, the SQL engine will do the following:
Read Row 1 from Table A, class is null, convert to 'N/A', hash this value.
Read Row 2 from Table A, class is null, convert to 'N/A', hash this value.
Read Row 3 from Table A, class is null, convert to 'N/A', hash this value.
Read Row 4 from Table A, class not null, hash this value.
Read Row 5 from Table A, class not null, hash this value.
Hash table C is now in memory.
Read Row 1 from Table B, class is null, convert to 'N/A', hash the value.
Compare hashed value to hash table in memory, for each match add a row to the result set. 3 rows are found, A1, A2, and A3. Results are added A1B1, A2B1, A3B1.
Read Row 2 from Table B, class is null, convert to 'N/A', hash the value.
Compare hashed value to hash table in memory, for each match add a row to the result set. 3 rows are found, A1, A2, and A3. Results are added A1B2, A2B2, A3B2.
Read Row 3 from Table B, class is null, convert to 'N/A', hash the value.
Compare hashed value to hash table in memory, for each match add a row to the result set. 3 rows are found, A1, A2, and A3. Results are added A1B3, A2B3, A3B3.
In first case, because each null is different, database doesn't use optimization (for every row from a check each row from table b).
In second case database firstly change all nulls to 'N/A' and then only compare a.class and b.class, using optimization
Comparing nulls in Oracle is very time-consuming. Null is undefined value - one null is different from other null.
Compare result of two almost identical queries:
select 1 from dual where null is null
select 1 from dual where null = null
Only first query with special is null clause return correct answer. Therefore, the null values can not be indexed.
Try this one:
SELECT a from Table1 a JOIN JTable1 b ON a.class = b.class
where a.class is null
union all
SELECT a from Table1 a JOIN JTable1 b ON a.class = b.class
where b.class is null
should be magnatudes faster
The explanation is simple:
First one has to use nested loops in join operation, it always happened when you use OR operation.
Second one has to use hash join operation, which faster then previous one.
Why don't you make it little bit easier.
like
SELECT *
FROM a,b
WHERE
a.class(+)=b.class(+)
I think it's more readable.