SQL pitfall avoidance: Have you avoided pitfalls when in and not in encounter null?

Table of contents

0 data preparation

1 analysis

Case 1: When in contains null in the filter condition

Case 2: When there is NULL in the main table, NULL will be ignored when not in is used and not followed by a subquery, and NULL cannot be matched, that is, no NULL records can be queried

Case 3: When not in contains NULL

 Case 4: If not in is followed by a subquery, special attention should be paid to the selected field containing NULL values

2 Summary

0 data preparation

create table t as 
select '张三' as name,1 as class
union all
select '李四' as name,1 as class
union all
select '王五' as name,2 as class
union all
select '老六' as name,null as class
union all
select '陈七' as name, 4 as class
union all
select '赵八' as name, 5 as class
union all
select '孙九' as name, 5 as class

1 analysis

The original table data is as follows:

Case 1: When in contains null in the filter condition

select * from t where class in (null,'1')

in is equivalent to or, and the judgment of null is not is null but equal, so the judgment of NULL is always false

select * from t where class ='1' or class =null

 

If you want to get the result of NULL, you must convert the value of NULL, you can use the following SQL

select * from t where coalesce(class,'null') in ('null','1')

 

Conclusion: When in contains null, no NULL result will be obtained

Case 2: When there is NULL in the main table, NULL will be ignored when not in is used and not followed by a subquery, and NULL cannot be matched, that is, no NULL records can be queried

select * from t where class not in ('1','2')

Case 3: When not in contains NULL

select * from t where class not in ('1','2',null)


not in is equivalent to the and condition, as long as there is one false, then all are false. We know that in not in is judged by the equal sign (=), and is not null will not be used for null, so the above is rewritten as:

select * from t where class !='1'and !='2'and !=null

The result is as follows:


Since the interpretation is not equal to NULL, it will always be false, and all the conditional judgments are false, and where is false,
then the result will return nothing. For the case of filtering null, you can rewrite it like this, convert null to the string 'null', The SQL is as follows:

select * from t where coalesce(class,'null') not in ('1','2','null') 

 Case 4: If not in is followed by a subquery, special attention should be paid to the selected field containing NULL values

The following SQL:

select *
from t
where class not in (
    select class
    from t t1
    where coalesce(t1.class, 'null') in (1, 2, 'null'))

 The final returned result is empty because the subquery contains NULL values. Special attention must be paid to this situation. When not in contains subqueries, if the result contains NULL values, no results will be found. At this time It should be necessary to actively filter out NULL values ​​in subqueries.

create table t1 as
select 1 as class
union all
select 2 as class
union all
select 3 as class
union all
select 4 as class
union all
select null as class
union all
select null as class

select *
from t
where class not in (
    select class
    from t1
    )

end result is empty

 The correct way to write it is as follows:

select *
from t
where class not in (
    select class
    from t1
    where class is not null
    )

Or use not exists instead of not in. Note that the uses of the exists function and in are different.

exists is actually a high-order predicate. The so-called high-order means that the number of input rows is often multiple rows, a set, which is different from other predicate judgments. The input value of other predicates is generally a scalar value (single value) , we know that the parameter of EXISTS is a collection of row data, the reason for saying this is because no matter what column is selected in the subquery, it is the same for EXISTS. In the subquery of EXISTS, the list of SELECT clauses can be written in the following three ways.

select *
from t
where NOT EXISTS (
    select t1.class
    from t1
where t.class=t1.class
    )

====================
select *
from t
where NOT EXISTS (
    select 1
    from t1
where t.class=t1.class
    )
====================
select *
from t
where NOT EXISTS (
    select *
    from t1
where t.class=t1.class
    )

 The result is as follows:

OK
t.name  t.class
老六    NULL
孙九    NULL
赵八    5
Time taken: 39.269 seconds, Fetched: 3 row(s)

Use a diagram to summarize the difference between general predicates and EXISTS

 

There is a problem here, the results in our subquery are as follows:

select class
    from t1
    where class is not null

So is the above result equivalent to the following SQL?

select * from t where class not in (1,2,3,4)

 Execute the above SQL: we get the following results

 Obviously, the two SQLs are not equivalent. That is to say, when there is a subquery in not in, the NULL in the main table will not be ignored, and the result of NULL in the main table can be obtained. When the not in is a constant value, the NULL in the main table The NULL is ignored, which is a bit of a pitfall.

If you have to filter out NULL values, you can write as follows 

select *
from t
where coalesce(class,'null') not in (
    select coalesce(class,'null')
    from t1
    )

2 Summary

  • (1) When there is NULL in the filter condition in in, regardless of whether in is followed by a constant or NULL in the main table of the subquery, it will not be filtered. At this time, the COALESCE() function can be used to convert the NULL value for filtering.
  • (2) When there is NULL in the main table and not in is used, if not in is followed by a constant, there will be no NULL in the filtered result, and the NULL value will be ignored. If not in is followed by a subquery, the filtered result will be There is a NULL value, it is amazing, if you need NULL to exist, convert it
  • (3) When not in contains a NULL value, no matter whether it is followed by a constant or a subquery, no result will be returned. This must be noted, especially when it is a subquery, it is necessary to convert NULL or filter NULL according to business requirements value

In short, the general problem is not big when using in, but it is particularly important when using not in, combined with the proper use of this article, the reason for such a
large difference is the judgment of NULL, which is essentially null or is not null , the judgment of in or
not in is equal to (=), so the judgment of NULL is invalid and needs to be kept in mind.

Guess you like

Origin blog.csdn.net/godlovedaniel/article/details/125376244