SQL에서 EXISTS와 IN의 차이점은 무엇입니까?


443

SQL 에서 EXISTSand IN절의 차이점은 무엇입니까 ?

언제 사용해야 EXISTS하고 언제 사용해야 IN합니까?

답변:


224

exists키워드는 그런 식으로 사용할 수 있지만, 정말 그것을 피하기 계산하는 방법으로 의도 :

--this statement needs to check the entire table
select count(*) from [table] where ...

--this statement is true as soon as one match is found
exists ( select * from [table] where ... )

이보다 훨씬 빠를 수있는 if조건문 이있는 경우 가장 유용합니다 .existscount

in당신이 전달하는 정적 목록이 어디에 가장 사용된다 :

 select * from [table]
 where [field] in (1, 2, 3)

in명령문에 테이블이 있으면를 사용하는 것이 더 합리적 join이지만 대부분 중요하지 않습니다. 쿼리 최적화 프로그램은 동일한 계획을 어느 쪽이든 반환해야합니다. 일부 구현 (대부분 Microsoft SQL Server 2000과 같은 오래된 in쿼리 )에서 쿼리는 항상 중첩 된 조인 계획을 얻는 반면 join쿼리는 적절히 중첩, 병합 또는 해시 를 사용합니다. 보다 현대적인 구현은 더 똑똑하고 in사용될 때에도 계획을 조정할 수 있습니다 .


2
"in 문에 테이블이있을 때 조인을 사용하는 것이 더 타당하지만 실제로는 중요하지 않습니다. 쿼리 최적화 프로그램은 동일한 계획을 어느 쪽이든 반환합니다."에 대해 자세히 설명 할 수 있습니까? 쿼리 최적화 프로그램 부분이 JOIN아니라의 대체품으로 사용할 수있는 부분 입니다 IN.
farthVader

select * from [table] where [field] in (select [field] from [table2])와 동일한 결과 (및 쿼리 계획)를 반환합니다 select * from [table] join [table2] on [table2].[field] = [table].[field].

@Sander는하지 않습니다 : 첫 번째 쿼리는에서 모든 열을 table반환하고 두 번째 쿼리는 table및 에서 모든 것을 반환합니다 table2. 일부 (대부분 오래된) SQL 데이터베이스에서는 in쿼리가 중첩 조인으로 구현되는 반면 join쿼리는 중첩, 병합, 해시 등이 가능합니다.
Keith

2
좋아, 나는 select 절에 열을 지정해야하지만 쿼리는 "같은 계획을 어느 쪽이든 반환 할 것"이라고 명확하게 설명하기 때문에 대답을 업데이트해야합니다.

existscase 문 내에서 사용될 수 있으므로, 그 방법으로도 편리 할 수 ​​있습니다.select case when exists (select 1 from emp where salary > 1000) then 1 else 0 end as sal_over_1000
smooth_smoothie

125

EXISTS쿼리가 결과를 반환했는지 여부를 알려줍니다. 예 :

SELECT * 
FROM Orders o 
WHERE EXISTS (
    SELECT * 
    FROM Products p 
    WHERE p.ProductNumber = o.ProductNumber)

IN 하나의 값을 여러 값과 비교하는 데 사용되며 다음과 같이 리터럴 값을 사용할 수 있습니다.

SELECT * 
FROM Orders 
WHERE ProductNumber IN (1, 10, 100)

다음과 같이 IN절 과 함께 쿼리 결과를 사용할 수도 있습니다 .

SELECT * 
FROM Orders 
WHERE ProductNumber IN (
    SELECT ProductNumber 
    FROM Products 
    WHERE ProductInventoryQuantity > 0)

3
하위 쿼리가 결과를 반환하지 않는 경우 마지막 쿼리는 실패 할 수 있으므로 위험합니다. 절 '에서'... 적어도 1 인수가 필요합니다
user2054927

40
@ user2054927 하위 쿼리가 행을 반환하지 않으면 마지막 쿼리는 행을 올바르게 반환하지 않습니다.
Tony Andrews

가장 좋은 답변입니다.
Aminadav Glickshtein

81

규칙 최적화 프로그램을 기반으로 :

  • EXISTSIN하위 쿼리 결과가 매우 큰 경우 보다 훨씬 빠릅니다 .
  • INEXISTS하위 쿼리 결과가 매우 작을 때보 다 빠릅니다 .

비용 최적화 도구를 기반으로 :

  • 다른 점이 없다.

21
당신의 주장의 증거? IN이 EXISTS보다 빠를 것이라고 생각하지 않습니다!
Nawaz

22
@Nawaz IN이 항상 기존보다 느리다는 증거는 어떻습니까?
ceving

2
잘못 구현 된 쿼리 최적화 프로그램? 특정
RDBM

1
EXISTS는 순수한 부울 값을 반환하며, 이는 문자열 또는 BIT / 부울 유형보다 큰 값을 비교하는 것보다 항상 빠릅니다. IN은 부울 비교 일 수도 있고 아닐 수도 있습니다. 프로그래밍은 안정성 (ACID의 일부)에 대해 EXPLICIT 사용을 선호하기 때문에 일반적으로 EXISTS가 선호됩니다.
clifton_h

2
왜 이렇게 여러 차례 찬성 되었습니까? 이 가정에 근거한 진술이 일반적으로 사실 인 이유는 전혀 없습니다.
Lukas Eder

40

나는 그들이 당신이하는 일을 알고 따라서 다르게 사용된다고 가정하므로, 나는 당신의 질문을 다음과 같이 이해할 것입니다 : 언제 EXISTS 대신 IN을 사용하도록 SQL을 다시 작성하는 것이 좋을까요?

이것이 공정한 가정입니까?


편집 : 내가 묻는 이유는 많은 경우 IN을 기반으로 SQL을 다시 작성하여 EXISTS를 대신 사용할 수 있고 그 반대도 가능하며 일부 데이터베이스 엔진의 경우 쿼리 최적화 프로그램이 두 가지를 다르게 취급하기 때문입니다.

예를 들어 :

SELECT *
FROM Customers
WHERE EXISTS (
    SELECT *
    FROM Orders
    WHERE Orders.CustomerID = Customers.ID
)

다시 쓸 수 있습니다 :

SELECT *
FROM Customers
WHERE ID IN (
    SELECT CustomerID
    FROM Orders
)

또는 조인

SELECT Customers.*
FROM Customers
    INNER JOIN Orders ON Customers.ID = Orders.CustomerID

그래서 내 질문은 여전히 ​​존재합니다. 원래 포스터는 IN과 EXISTS 가하는 일에 대해 궁금해하고 그것을 사용하는 방법을 알고 있습니까? 아니면 EXISTS를 대신하여 IN을 사용하여 SQL을 다시 작성하거나 그 반대의 경우에도 좋은 아이디어입니까?


12
OP에 대해 모르겠지만이 질문에 대한 답변을 원합니다! ID를 반환하는 하위 쿼리와 함께 IN 대신 EXISTS를 언제 사용해야합니까?
Roy Tinker

8
JOIN, 당신은해야합니다DISTINCT
Jaider

4
훌륭한 데모이지만 질문에 대한 답은 거의 없습니다
Junchen Liu

28
  1. EXISTS보다 훨씬 빠르기 때문에 IN서브 쿼리 결과가 매우 큰 경우. 하위 쿼리 결과가 매우 작은 경우
    IN보다 빠릅니다 EXISTS.

    CREATE TABLE t1 (id INT, title VARCHAR(20), someIntCol INT)
    GO
    CREATE TABLE t2 (id INT, t1Id INT, someData VARCHAR(20))
    GO
    
    INSERT INTO t1
    SELECT 1, 'title 1', 5 UNION ALL
    SELECT 2, 'title 2', 5 UNION ALL
    SELECT 3, 'title 3', 5 UNION ALL
    SELECT 4, 'title 4', 5 UNION ALL
    SELECT null, 'title 5', 5 UNION ALL
    SELECT null, 'title 6', 5
    
    INSERT INTO t2
    SELECT 1, 1, 'data 1' UNION ALL
    SELECT 2, 1, 'data 2' UNION ALL
    SELECT 3, 2, 'data 3' UNION ALL
    SELECT 4, 3, 'data 4' UNION ALL
    SELECT 5, 3, 'data 5' UNION ALL
    SELECT 6, 3, 'data 6' UNION ALL
    SELECT 7, 4, 'data 7' UNION ALL
    SELECT 8, null, 'data 8' UNION ALL
    SELECT 9, 6, 'data 9' UNION ALL
    SELECT 10, 6, 'data 10' UNION ALL
    SELECT 11, 8, 'data 11'
  2. 쿼리 1

    SELECT
    FROM    t1 
    WHERE   not  EXISTS (SELECT * FROM t2 WHERE t1.id = t2.t1id)

    쿼리 2

    SELECT t1.* 
    FROM   t1 
    WHERE  t1.id not in (SELECT  t2.t1id FROM t2 )

    t1id에 null 값이 있으면 Query 1이 값을 찾지 만 Query 2는 null 매개 변수를 찾을 수 없습니다.

    내 말 IN은 아무것도 null과 비교할 수 없으므로 null에 대한 결과는 없지만 EXISTS모든 것을 null과 비교할 수 있다는 의미 입니다.


이 답변은 Tom Kite의 정서에 대한 합리적인 요약입니다 ( asktom.oracle.com/pls/asktom/… )
Jeromy French

나는이 대답이 직관을 바탕으로하고 있다고 생각합니다. 그러나 보편적으로 사실 일 수는 없습니다. 예를 들어, Ingres의 경우에는 거의 동일하지 않습니다 . 동일한 SQL 쿼리를 동일한 QUEL 쿼리로 구문 분석하여 동일한 방법으로 여러 가지 방법으로 작성할 때 SQL의 풍부함이 없습니다.
어느 날

t2.id가 "NOT NULL"로 정의 된 경우에만이 두 쿼리가 논리적으로 동일합니다. 테이블 정의에 종속성이없는 동등성을 부여하려면 두 번째 쿼리는 "SELECT t1. * FROM t1 WHERE t1.id in in (SELECT t2.id FROM t2 여기서 t2.id가 null이 아님 )"
David דודו Markovitz

16

IN연산자를 사용하는 경우 SQL 엔진은 내부 쿼리에서 가져온 모든 레코드를 스캔합니다. 반면에을 사용하는 경우 EXISTSSQL 엔진은 일치하는 것을 발견하자마자 스캔 프로세스를 중지합니다.


10

IN 은 동등 관계 (또는 NOT이 앞에 오는 경우 부등식) 만 지원합니다 . = any / = some
동의어입니다 . 예 :

select    * 
from      t1 
where     x in (select x from t2)
;

EXISTSIN을 사용하여 표현할 수없는 다양한 유형의 관계를 지원합니다 . 예 :-

select    * 
from      t1 
where     exists (select    null 
                  from      t2 
                  where     t2.x=t1.x 
                        and t2.y>t1.y 
                        and t2.z like '℅' || t1.z || '℅'
                  )
;

그리고 다른 쪽지에-

EXISTSIN의 성능 및 기술적 차이점 특정 공급 업체의 구현 / 제한 / 버그로 인해 발생할 수 있지만 데이터베이스 내부에 대한 이해 부족으로 인해 신화에 지나지 않습니다.

테이블 정의, 통계 정확도, 데이터베이스 구성 및 옵티 마이저 버전은 모두 실행 계획 및 성능 메트릭에 영향을 미칩니다.


성능에 대한 귀하의 의견에 찬성 투표 : 특정 DBMS에 중점을 두지 않으면 서 가장 적합한 것을 해결하는 것은 최적화 프로그램에 달려 있다고 가정해야합니다.
Manngo

9

Exists키워드는 참 또는 거짓으로 평가하지만, IN해당 서브 쿼리 열의 모든 값을 비교하는 키워드. 다른 하나 Select 1Exists명령 과 함께 사용할 수 있습니다 . 예:

SELECT * FROM Temp1 where exists(select 1 from Temp2 where conditions...)

그러나 IN덜 효율적이므로 Exists빠릅니다.


5

내 생각 엔

  • EXISTS쿼리 결과를 다른 하위 쿼리와 일치시켜야 할 때입니다. SubQuery 결과가 일치하는 위치에서 Query # 1 결과를 검색해야합니다. Join of Kind .. 예를 들어 주문 테이블 # 2도 배치 한 고객 테이블 # 1을 선택하십시오.

  • IN은 특정 열의 값이 IN목록 (1,2,3,4,5)에 있는지 검색하는 것입니다. 예를 들어 다음 우편 번호에있는 고객을 선택하십시오. 즉 zip_code 값은 (....) 목록에 있습니다.

적절하게 읽는다고 생각 될 때 (의사 소통이 더 나을 때).


4

차이점은 다음과 같습니다.

select * 
from abcTable
where exists (select null)

위의 쿼리는 모든 레코드를 반환하지만 아래의 쿼리는 빈 레코드를 반환합니다.

select *
from abcTable
where abcTable_ID in (select null)

시도하고 출력을 관찰하십시오.


1
흠 ... 오류 : [SQL0104] 토큰)이 유효하지 않습니다. 두 경우 모두. 특정 RDBMS를 가정하고 있습니까?
jmarkmurphy

3

내 지식에 따라 하위 쿼리가 NULL값을 반환 하면 전체 문이됩니다 NULL. 이 경우 EXITS키워드를 사용하고 있습니다. 하위 쿼리에서 특정 값을 비교하려면 IN키워드를 사용합니다 .


3

내부 쿼리에서 가져온 쿼리 수에 따라 속도가 더 빠릅니다.

  • 내부 쿼리가 수천 개의 행을 가져 오는 경우 EXIST가 더 좋습니다.
  • 내부 쿼리에서 몇 개의 행을 가져 오면 IN이 더 빠릅니다.

EXIST는 true 또는 false로 평가되지만 IN은 여러 값을 비교합니다. 기록이 존재하는지 모르는 경우 EXIST를 선택해야합니다.


3

그 이유는 EXISTS 연산자가 "적어도 발견 된"원칙에 따라 작동하기 때문입니다. 일치하는 행이 하나 이상 발견되면 true를 리턴하고 테이블 스캔을 중지합니다.

반면에 IN 연산자가 하위 쿼리와 결합되면 MySQL은 먼저 하위 쿼리를 처리 한 다음 하위 쿼리의 결과를 사용하여 전체 쿼리를 처리해야합니다.

일반적으로 하위 쿼리에 많은 양의 데이터가 포함 된 경우 EXISTS 연산자는 더 나은 성능을 제공합니다.

그러나 서브 쿼리에서 리턴 된 결과 세트가 매우 작은 경우 IN 연산자를 사용하는 쿼리가 더 빠르게 수행됩니다.


1

우리가 NULL 값을 다루지 않는 한 둘 다 동일해야한다는 것을 이해합니다.

쿼리가 = NULL 값을 반환하지 않는 것과 같은 이유는 NULL입니다. http://sqlinthewild.co.za/index.php/2010/02/18/not-exists-vs-not-in/

부울 대 비교기 인수에 관해서는 부울을 생성하려면 두 값을 비교해야하며 그것이 if 조건이 작동하는 방식입니다. 따라서 IN과 EXISTS가 어떻게 다르게 동작하는지 이해하지 못합니다.



0

하위 쿼리가 둘 이상의 값을 반환하면 조건에 지정된 열 내의 값이 하위 쿼리 결과 집합의 값과 일치하는 경우 외부 쿼리를 실행해야 할 수 있습니다. 이 작업을 수행하려면 in키워드 를 사용해야합니다 .

서브 쿼리를 사용하여 레코드 세트가 있는지 확인할 수 있습니다. 이를 위해 exists하위 쿼리와 함께 절 을 사용해야합니다 . exists키워드는 항상 true 또는 false 값을 반환합니다.


0

나는 이것이 정답이라고 생각합니다. 시스템에서 해당 기능을 개발 한 사람들로부터 왜 확인하지 않습니까?

MS SQL 개발자 인 경우 다음은 Microsoft의 답변입니다.

IN:

지정된 값이 하위 쿼리 또는 목록의 값과 일치하는지 확인합니다.

EXISTS:

행이 있는지 테스트 할 하위 쿼리를 지정합니다.



-1

기존보다 IN보다 성능이 빠릅니다. 대부분의 필터 기준이 하위 쿼리에 있으면 IN을 사용하는 것이 좋으며 대부분의 필터 기준이 기본 쿼리에 있으면 EXISTS를 사용하는 것이 좋습니다.


그 주장은 실제로 어떤 증거로 뒷받침되지 않습니다.
Lukas Eder

-2

IN 연산자를 사용하는 경우 SQL 엔진은 내부 쿼리에서 가져온 모든 레코드를 스캔합니다. 반면에 EXISTS를 사용하는 경우 SQL 엔진은 일치하는 것을 발견하자마자 스캔 프로세스를 중지합니다.


@ziggy 설명? 이것은 받아 들인 대답이 말하는 것과 거의 같습니다. 반드시 모든 단일 레코드를 확인하십시오. 존재하는 레코드가 하나만 발견되면 중지 할 수 있습니다.
벤 Thurley

아뇨, 정확하지 않습니다. INEXISTS등가물 서로 변환 될 수있다.
Lukas Eder
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.