Klauzula IN z wartością NULL lub IS NULL


84

Bazą danych jest Postgres

Czy mogę użyć wartości NULL dla klauzuli IN? przykład:

SELECT *
FROM tbl_name
WHERE id_field IN ('value1', 'value2', 'value3', NULL)

Chcę ograniczyć się do tych czterech wartości.

Wypróbowałem powyższą instrukcję i nie działa, cóż, wykonuje, ale nie dodaje rekordów z NULL id_fields.

Próbowałem również dodać warunek LUB, ale to po prostu sprawia, że ​​zapytanie jest uruchamiane i uruchamiane bez końca.

SELECT *
FROM tbl_name
WHERE other_condition = bar
AND another_condition = foo
AND id_field IN ('value1', 'value2', 'value3')
OR id_field IS NULL

Jakieś sugestie?


10
inOświadczenie będzie analizowany identycznie field=val1 or field=val2 or field=val3. Umieszczenie tam wartości zerowej sprowadzi się do tego, field=nullco nie zadziała.
Marc B

1
drugie zapytanie powinno być poprawne. jakie inne rzeczy są w twojej whereklauzuli?
Daniel A. White

@Daniel A. White, zaktualizowany, aby odzwierciedlić zapytanie z większą liczbą warunków
Phill Pafford

Odpowiedzi:


124

inOświadczenie będzie analizowany identycznie field=val1 or field=val2 or field=val3. Umieszczenie tam wartości zerowej sprowadzi się do tego, field=nullco nie zadziała.

( Komentarz przez Marc B )

Zrobiłbym to dla jasności

SELECT *
FROM tbl_name
WHERE 
(id_field IN ('value1', 'value2', 'value3') OR id_field IS NULL)

Ach, to się udało, dzięki! Więc zawijanie pól dodaje oba warunki do klauzuli WHERE? Dla wyjaśnienia
Phill Pafford

1
@Phill - to był problem z kolejnością operacji.
Daniel A. White

20

Twoje zapytanie nie powiodło się z powodu pierwszeństwa operatorów . ANDwiąże się wcześniej OR!
Potrzebujesz pary nawiasów, co nie jest kwestią „jasności”, ale czystą logiczną koniecznością .

SELECT *
FROM   tbl_name
WHERE  other_condition = bar
AND    another_condition = foo
AND   (id_field IN ('value1', 'value2', 'value3') OR id_field IS NULL)

Dodane nawiasy zapobiegają ANDwcześniejszemu wiązaniu OR. Gdyby nie było innych WHEREwarunków (nie AND), nie potrzebowałbyś nawiasów. Przyjęta odpowiedź jest pod tym względem nieco myląca.


15
SELECT *
FROM tbl_name
WHERE coalesce(id_field,'unik_null_value') 
IN ('value1', 'value2', 'value3', 'unik_null_value')

Aby wyeliminować zero z czeku. Biorąc pod uwagę wartość null w id_field, funkcja łączenia zamiast null zwróciłaby „unik_null_value”, a dodając „unik_null_value do listy IN-lista, zapytanie zwróciłoby posty, w których id_field ma wartość 1-3 lub null.


2
Małe wyjaśnienie byłoby pomocne dla przyszłych czytelników. W jaki sposób Twój kod pomaga rozwiązać problem?
showdev

9

Pytanie, na które odpowiedział Daniel, jest całkowicie w porządku. Chciałem zostawić notatkę dotyczącą wartości NULLS. Należy zachować ostrożność przy używaniu operatora NOT IN, gdy kolumna zawiera wartości NULL. Nie otrzymasz żadnych danych wyjściowych, jeśli kolumna zawiera wartości NULL i używasz operatora NOT IN. Oto jak to zostało wyjaśnione tutaj http://www.oraclebin.com/2013/01/beware-of-nulls.html , bardzo dobry artykuł, na który natknąłem się i pomyślałem o udostępnieniu go.


Nie jestem pewien, ilu użytkowników napotkało ten problem, ale miałem dokładnie ten problem z mieszaniem wartości null i operatorem NOT IN i sprawdzałem go przez ostatnie dwie godziny. TO jest sprawca ...
Govind Rai

1
Link nie działa.
Dag Høidahl

1
To coś teraz żyje.
zawsze uczący się

3

Uwaga: Ponieważ w odpowiedzi Sushant Butta ktoś twierdził, że link zewnętrzny jest martwy , opublikowałem tutaj treść jako oddzielną odpowiedź.

Uważaj na NULLS .

Dzisiaj natknąłem się na bardzo dziwne zachowanie zapytania podczas używania IN i NOT INoperatorów. Właściwie chciałem porównać dwie tabele i dowiedzieć się, czy wartość z table bistniała w, table aczy nie, i dowiedzieć się, jak zachowuje się, jeśli kolumna zawiera nullwartości. Dlatego właśnie stworzyłem środowisko do testowania tego zachowania.

Stworzymy tabelę table_a.

SQL> create table table_a ( a number);
Table created.

Stworzymy tabelę table_b.

SQL> create table table_b ( b number);
Table created.

Wstaw niektóre wartości do table_a.

SQL> insert into table_a values (1);
1 row created.

SQL> insert into table_a values (2);
1 row created.

SQL> insert into table_a values (3);
1 row created.

Wstaw niektóre wartości do table_b.

SQL> insert into table_b values(4);
1 row created.

SQL> insert into table_b values(3);
1 row created.

Teraz wykonamy zapytanie, aby sprawdzić istnienie wartości table_a, sprawdzając jej wartość table_bza pomocą INoperatora.

SQL> select * from table_a where a in (select * from table_b);
         A
----------
         3

Wykonaj poniższe zapytanie, aby sprawdzić, czy nie istnieje.

SQL> select * from table_a where a not in (select * from table_b);
         A
----------
         1
         2

Wynik przyszedł zgodnie z oczekiwaniami. Teraz wstawimy nullwartość do tabeli table_bi zobaczymy, jak zachowują się powyższe dwa zapytania.

SQL> insert into table_b values(null);
1 row created.

SQL> select * from table_a where a in (select * from table_b);
         A
----------
         3

SQL> select * from table_a where a not in (select * from table_b);

no rows selected

Pierwsze zapytanie zachowało się zgodnie z oczekiwaniami, ale co się stało z drugim zapytaniem? Dlaczego nie otrzymaliśmy żadnych wyników, co powinno się stać? Czy jest jakaś różnica w zapytaniu? Nie .

Zmiana jest w danych tabeli table_b. Wprowadziliśmy nullwartość do tabeli. Ale dlaczego tak się zachowuje? Podzielmy dwa zapytania na "AND"i "OR"operator.

Pierwsze zapytanie:

Pierwsze zapytanie będzie obsługiwane wewnętrznie, mniej więcej w ten sposób. Więc a nullnie spowoduje tutaj problemu, ponieważ moje pierwsze dwa operandy będą obliczane na truelub false. Ale mój trzeci operand a = nullnie będzie obliczany do trueani false. Oceni nulltylko.

select * from table_a whara a = 3 or a = 4 or a = null;

a = 3  is either true or false
a = 4  is either true or false
a = null is null

Drugie zapytanie:

Drugie zapytanie zostanie obsłużone jak poniżej. Ponieważ używamy "AND"operatora i wszystko inne niż truew którymkolwiek z operandów nie da mi żadnego wyniku.

select * from table_a whara a <> 3 and a <> 4 and a <> null;

a <> 3 is either true or false
a <> 4 is either true or false
a <> null is null

Jak więc sobie z tym radzimy? Wszystkie not nullwartości z tabeli wybierzemy table_bużywając NOT INoperatora.

SQL> select * from table_a where a not in (select * from table_b where b is not null);

         A
----------
         1
         2

Dlatego zawsze uważaj na NULLwartości w kolumnie podczas używania NOT INoperatora.

Uważaj na NULL !!


Doskonała odpowiedź. Właśnie odkryłem problem w swojej pracy. Bardzo, bardzo dziwne zachowanie Oracle.
oputyk

0

Wiem, że jest późno na odpowiedź, ale może być przydatna dla kogoś innego. Możesz użyć zapytania podrzędnego i przekonwertować wartość null na 0

SELECT *
FROM (SELECT CASE WHEN id_field IS NULL 
                THEN 0 
                ELSE id_field 
            END AS id_field
      FROM tbl_name) AS tbl
WHERE tbl.id_field IN ('value1', 'value2', 'value3', 0)

Jest to podobne do odpowiedzi Ove Halsetha przy użyciu koalescencji.
user890332

0

Nullodnosi się do braku danych. Nulljest formalnie zdefiniowana jako wartość niedostępna, nieprzypisana, nieznana lub niemożliwa do zastosowania (OCA Oracle Database 12c, SQL Fundamentals I Exam Guide, str. 87). Dlatego możesz nie widzieć rekordów z kolumnami zawierającymi wartości null, gdy te kolumny są ograniczone za pomocą klauzul „in” lub „not in”.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.