NULL 또는 IS NULL이있는 IN 절


85

Postgres는 데이터베이스입니다.

IN 절에 NULL 값을 사용할 수 있습니까? 예:

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

이 네 가지 값으로 제한하고 싶습니다.

위의 문을 시도했지만 작동하지 않습니다. 잘 실행되지만 NULL id_fields가있는 레코드를 추가하지 않습니다.

나는 또한 OR 조건을 추가하려고 시도했지만 이것은 쿼리를 실행하고 끝없이 실행합니다.

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

어떤 제안?


10
in문은 동일하게 해석됩니다 field=val1 or field=val2 or field=val3. 거기에 null을 넣으면 field=null작동하지 않을 것입니다.
Marc B

1
두 번째 쿼리가 맞아야합니다. 귀하의 where조항 에 다른 것은 무엇 입니까?
다니엘 A. 화이트

@Daniel A. White, 더 많은 조건으로 쿼리를 반영하도록 업데이트 됨
Phill Pafford

답변:


125

in문은 동일하게 해석됩니다 field=val1 or field=val2 or field=val3. 거기에 null을 넣으면 field=null작동하지 않을 것입니다.

( 주석 의해 마크 B )

나는 명확성을 위해 이것을 할 것입니다

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

아, 해냈어, 고마워! 따라서 필드를 래핑하면 WHERE 절에 두 조건이 모두 추가됩니까? 설명을 위해
Phill Pafford 2011-06-15

1
@Phill-작업 ​​순서 문제였습니다.
다니엘 A. 화이트

20

연산자 우선 순위 로 인해 쿼리가 실패합니다 . AND전에 바인딩합니다 OR!
"명확성"의 문제가 아니라 순수한 논리 필요성 의 문제인 한 쌍의 괄호가 필요 합니다.

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

추가 된 괄호는 AND앞에 바인딩을 방지 OR합니다. 다른 WHERE조건 (아니오 AND)이 없으면 괄호 가 필요 하지 않습니다 . 이 점에서 받아 들여지는 대답은 약간 오해의 소지가 있습니다.


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

그래서 당신은 검사에서 널을 제거합니다. id_field에 null 값이 주어지면 coalesce 함수는 null 대신 'unik_null_value'를 반환하고 IN-list에 'unik_null_value를 추가하여 쿼리는 id_field가 value1-3 또는 null 인 게시물을 반환합니다.


2
약간의 설명이 미래의 독자들에게 도움이 될 것입니다. 코드가 문제 해결에 어떻게 도움이됩니까?
showdev

9

Daniel이 대답 한 질문은 매우 훌륭합니다. NULLS에 관한 메모를 남기고 싶었습니다. 열에 NULL 값이 포함 된 경우 NOT IN 연산자를 사용할 때주의해야합니다. 열에 NULL 값이 포함되어 있고 NOT IN 연산자를 사용하는 경우 출력이 표시되지 않습니다. 이것이 여기 http://www.oraclebin.com/2013/01/beware-of-nulls.html 에서 설명하는 방법입니다.이 기사는 제가 만나서 공유 할 것을 생각한 아주 좋은 기사입니다.


얼마나 많은 사용자가이 문제를 경험했는지는 확실하지 않지만 null과 NOT IN 연산자를 혼합하는 정확한 문제가 있었고 지난 2 시간 동안 문제를 해결했습니다. 이건 ... 범인입니다
빈드 라이

1
링크가 끊어졌습니다.
Dag Høidahl

1
좋아요는 지금 살아 있습니다.
always-a-learner

3

참고 : 누군가 Sushant Butta의 답변 에서 외부 링크가 죽었다고 주장했기 때문에 여기에 별도의 답변으로 콘텐츠를 게시했습니다.

NULLS에 주의하십시오 .

오늘 저는 IN과 NOT IN연산자 를 사용하는 동안 매우 이상한 쿼리 동작을 발견했습니다 . 실제로 두 테이블을 비교하여 값이 table b존재 하는지 여부를 table a확인하고 열에 null값이 포함 된 경우 그 동작을 확인하고 싶었습니다 . 그래서 방금이 동작을 테스트하기위한 환경을 만들었습니다.

테이블을 생성합니다 table_a.

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

테이블을 생성합니다 table_b.

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

일부 값을 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.

일부 값을 table_b.

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

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

이제 연산자 table_atable_b사용하여 값을 확인하여 값 의 존재를 확인하는 쿼리를 실행합니다 IN.

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);
         A
----------
         1
         2

예상대로 출력되었습니다. 이제 null테이블에 값을 삽입 table_b하고 위의 두 쿼리가 어떻게 작동하는지 살펴 보겠습니다.

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

첫 번째 쿼리는 예상대로 작동했지만 두 번째 쿼리는 어떻게 되었습니까? 출력이 나오지 않은 이유는 무엇입니까? 쿼리에 차이가 있습니까? 아니 .

변경 사항은 테이블의 데이터에 table_b있습니다. 우리는 null표에 값을 도입했습니다 . 하지만 어떻게 이런 식으로 작동합니까? 두 쿼리를 "AND"and "OR"연산자 로 나눕니다 .

첫 번째 쿼리 :

첫 번째 쿼리는 다음과 같이 내부적으로 처리됩니다. A는 그래서 null여기에 문제를 만들지 않습니다 처음 두 개의 피연산자 중 하나를에 평가합니다으로 truefalse. 그러나 세 번째 피연산자 a = null에 둘을 평가하지 않습니다 true아니다 false. null로만 평가 됩니다.

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

두 번째 쿼리 :

두 번째 쿼리는 다음과 같이 처리됩니다. 우리는 "AND"연산자를 사용하고 있기 때문에 true피연산자 이외의 다른 것은 나에게 출력을 제공하지 않습니다.

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

그럼 어떻게 처리할까요? 연산자 를 사용하는 동안 not null테이블에서 모든 값을 선택합니다 .table_bNOT IN

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

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

따라서 연산자 NULL를 사용하는 동안 항상 열의 값에 주의 하십시오 NOT IN.

NULL을 조심하세요 !!


훌륭한 대답입니다. 내 작업에서 문제를 발견했습니다. Oracle의 매우 이상한 동작.
oputyk

0

대답하기 늦었지만 다른 사람에게 유용 할 수 있음을 알고 있습니다. 하위 쿼리를 사용하고 null을 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)

이것은 합체를 사용하는 Ove Halseth의 대답과 유사합니다.
user890332

0

Null데이터가 없음을 나타냅니다. Null공식적으로 사용할 수 없거나 할당되지 않았거나 알 수 없거나 적용 할 수없는 값으로 정의됩니다 (OCA Oracle Database 12c, SQL Fundamentals I Exam Guide, p87). 따라서 해당 열이 "in"또는 "not in"절을 사용하여 제한되는 경우 null 값이 포함 된 열이있는 레코드를 볼 수 없습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.