복붙노트

[SQL] NOT 거래 SQL에 존재하는 반대 경우를 제외하고는 사용 하는가?

SQL

NOT 거래 SQL에 존재하는 반대 경우를 제외하고는 사용 하는가?

나는 최근 동료에 의해 작성된 코드 읽기를 통해 SQL Server의 새로운 "EXCEPT"절 (조금 늦게, 나는 ... 알고)의 존재를 알게되었다. 그것은 정말 나를 놀라게!

그러나 나는 그것의 사용에 관한 몇 가지 질문이 있습니다 그것을 사용하는 것이 좋습니다 때? "... AND NOT EXISTS"차이가 사용하는 상호 연관된 쿼리 대를 사용하는 사이에, 성능 현명한 있나요?

BOL I에서의 기사를 제외하고 읽은 후에는 두 번째 옵션에 대한 단지 속기라고 생각하지만 난 그것을 사용하는 몇 가지 쿼리를 재 작성 할 때 놀랐습니다 (그들은 구문 훨씬 더 익숙한 나에게 "AND NOT EXISTS"한 정도) 한 후 확인 실행 계획 - 놀라운! 버전을 제외하고는 짧은 실행 계획을 가지고, 또한, 빠른 실행. 이것은 항상 그래서?

내가 알고 싶습니다 그래서이 강력한 도구를 사용하기위한 지침은 무엇입니까?

해결법

  1. ==============================

    1.매칭으로 취급 NULL 값을 제외합니다.

    매칭으로 취급 NULL 값을 제외합니다.

    이 쿼리 :

    WITH    q (value) AS
            (
            SELECT  NULL
            UNION ALL
            SELECT  1
            ),
            p (value) AS
            (
            SELECT  NULL
            UNION ALL
            SELECT  2
            )
    SELECT  *
    FROM    q
    WHERE   value NOT IN
            (
            SELECT  value
            FROM    p
            )
    

    빈 행 집합을 반환합니다.

    이 쿼리 :

    WITH    q (value) AS
            (
            SELECT  NULL
            UNION ALL
            SELECT  1
            ),
            p (value) AS
            (
            SELECT  NULL
            UNION ALL
            SELECT  2
            )
    SELECT  *
    FROM    q
    WHERE   NOT EXISTS
            (
            SELECT  NULL
            FROM    p
            WHERE   p.value = q.value
            )
    

    반환

    NULL
    1
    

    , 그리고 이것:

    WITH    q (value) AS
            (
            SELECT  NULL
            UNION ALL
            SELECT  1
            ),
            p (value) AS
            (
            SELECT  NULL
            UNION ALL
            SELECT  2
            )
    SELECT  *
    FROM    q
    EXCEPT
    SELECT  *
    FROM    p
    

    반환합니다 :

    1
    

    이 이상한 방식으로 동작하지만 순환 참조는 또한 재귀 CTE에 절을 제외하고 허용됩니다 : 그것은 이전 세트의 마지막 행을 제외한 모든 반환, 전체 이전 세트를 제외한 모든 것이 :

    WITH    q (value) AS
            (
            SELECT  1
            UNION ALL
            SELECT  2
            UNION ALL
            SELECT  3
            ),
            rec (value) AS
            (
            SELECT  value
            FROM    q
            UNION ALL
            SELECT  *
            FROM    (
                    SELECT  value
                    FROM    q
                    EXCEPT
                    SELECT  value
                    FROM    rec
                    ) q2
            )
    SELECT  TOP 10 *
    FROM    rec
    
    ---
    1
    2
    3
    -- original set
    1
    2
    -- everything except the last row of the previous set, that is 3
    1
    3
    -- everything except the last row of the previous set, that is 2
    1
    2
    -- everything except the last row of the previous set, that is 3, etc.
    1
    

    SQL 서버 개발자는 단지 그것을 금지 잊어 버린해야합니다.

  2. ==============================

    2.나는이 아닌 존재의 제외하고 분석을 많이하지 참여와 왼쪽 외부있다. 일반적으로 왼쪽 외부 조인 특히 기본 키에 합류, 누락 된 행을 찾기위한 가장 빠른 것입니다. 당신이 선택에 반환 작은 목록이 될 것입니다 알고있는 경우하지에 매우 빠르게 할 수 있습니다.

    나는이 아닌 존재의 제외하고 분석을 많이하지 참여와 왼쪽 외부있다. 일반적으로 왼쪽 외부 조인 특히 기본 키에 합류, 누락 된 행을 찾기위한 가장 빠른 것입니다. 당신이 선택에 반환 작은 목록이 될 것입니다 알고있는 경우하지에 매우 빠르게 할 수 있습니다.

    나는 코드를 재 작성 할 때 반환되는 내용 비교하는 많은 경우를 제외하고 사용합니다. 이전 코드 절약의 결과를 실행합니다. 모든 차이를 캡처 제외하고는 사용 후 새로운 코드 저장 결과를 실행합니다. 그것은 널 (null)을 포함한 모든 차이를받을 필요 특히, 차이를 찾을 수있는 매우 빠르고 쉬운 방법입니다. 즉석에서 쉽게 코딩을 위해 아주 좋은.

    그러나, 모든 상황은 다릅니다. 나는 내가 가르치고있는 모든 개발자에게 말한다. 시도 해봐. 타이밍 모두 다른 방식으로 작업을 수행합니다. 시간을 그것을 시도, 그것을 할.

  3. ==============================

    3.제외 두 전체 선택 전부 (페어링) 열을 비교한다. NOT 존재하는 하위 쿼리 절 키워드 존재하지 다음에 규정 된 조건에 accoding의 두 개 이상의 테이블을 비교합니다.

    제외 두 전체 선택 전부 (페어링) 열을 비교한다. NOT 존재하는 하위 쿼리 절 키워드 존재하지 다음에 규정 된 조건에 accoding의 두 개 이상의 테이블을 비교합니다.

    NOT EXISTS를 사용하여 다시 작성할 수 있습니다 EXCEPT. (ALL은 ROW_NUMBER를 사용하여 다시 작성 및 NOT EXISTS 할 수 제외).

    여기에서이있어

  4. ==============================

    4.SQL 서버의 실행 계획에 대한 회계가 없습니다. 그것은 완전히 임의의 것을 성능 문제를 가지고 때 난 항상 발견 (사용자의 관점에서를, 나는 확실히 알고리즘 작가는 이해할거야 왜) 하나의 구문은 다른 것보다 더 나은 실행 계획을 만들 때.

    SQL 서버의 실행 계획에 대한 회계가 없습니다. 그것은 완전히 임의의 것을 성능 문제를 가지고 때 난 항상 발견 (사용자의 관점에서를, 나는 확실히 알고리즘 작가는 이해할거야 왜) 하나의 구문은 다른 것보다 더 나은 실행 계획을 만들 때.

    이 경우, 쿼리 매개 변수 비교에 대해 뭔가 바로 가기 알아낼 SQL을 수는 수없는 직선 select 문에서. 나는 알고리즘의 부족입니다 확신합니다. 즉, 논리적으로 같은 일을 보간 할 수 있지만 쿼리 존재에 알고리즘은 번역하지 않습니다. 안정적으로 오래 걸릴 것입니다 그것을 알아낼 수있는 알고리즘이 쿼리 자체보다 실행하기 위해, 또는 적어도 알고리즘 디자이너가 그렇게 생각하기 때문에 가끔은이다.

  5. ==============================

    5.쿼리가 미세 조정되면 다음 절을 제외하고의 사용 / W 성능에 차이 B가없는 나는 그것으로 내 상관 관계 쿼리를 변경 한 후 EXCEPT 실행할 때 NOT는 반환하기 때문에 내가 놀랐습니다 .. .. NOT IN / 처음 존재 상관 쿼리가 22 초에 돌아 오는 동안 단 7 초에 결과 .. 나는 내 상관 쿼리 및 reran에 별개의 절을 사용 .. 그것도 .. 그래서 EXCEPT 7 초에 반환 당신이 알고하지 않거나하지 않는 좋은 잘 모두 현명 동일한 성능입니다 그렇지 않으면 쿼리를 튜닝에 시간이 ..

    쿼리가 미세 조정되면 다음 절을 제외하고의 사용 / W 성능에 차이 B가없는 나는 그것으로 내 상관 관계 쿼리를 변경 한 후 EXCEPT 실행할 때 NOT는 반환하기 때문에 내가 놀랐습니다 .. .. NOT IN / 처음 존재 상관 쿼리가 22 초에 돌아 오는 동안 단 7 초에 결과 .. 나는 내 상관 쿼리 및 reran에 별개의 절을 사용 .. 그것도 .. 그래서 EXCEPT 7 초에 반환 당신이 알고하지 않거나하지 않는 좋은 잘 모두 현명 동일한 성능입니다 그렇지 않으면 쿼리를 튜닝에 시간이 ..

  6. from https://stackoverflow.com/questions/1662902/when-to-use-except-as-opposed-to-not-exists-in-transact-sql by cc-by-sa and MIT license