JOINS, EXISTS or IN which is better? Few questions on SQL

前端 未结 8 1790
不思量自难忘°
不思量自难忘° 2021-01-14 07:58

I have few questions on SQL..

  1. How to analyze the performance of a query? Any software, inbuilt features of MSSQL server 2005/2008?

  2. What shou

8条回答
  •  轻奢々
    轻奢々 (楼主)
    2021-01-14 08:42

    They each behave differently: it is not a performance choice

    The only correct and reliable choice is EXISTS or NOT EXISTS that works all the time.

    • JOIN may needs DISTINCT
    • WHERE/LEFT JOIN would needs correct placement of the filter
    • NOT IN fails on NULL

    Example:

    DECLARE @Parent TABLE (foo int NULL)
    INSERT @Parent (foo) VALUES (1)
    INSERT @Parent (foo) VALUES (2)
    INSERT @Parent (foo) VALUES (3)
    INSERT @Parent (foo) VALUES (4)
    
    DECLARE @Child TABLE (bar int NULL, foo int NULL)
    INSERT @Child (bar, foo) VALUES (100, 1)
    INSERT @Child (bar, foo) VALUES (200, 2)
    INSERT @Child (bar, foo) VALUES (201, 2)
    INSERT @Child (bar, foo) VALUES (300, NULL)
    INSERT @Child (bar, foo) VALUES (301, NULL)
    INSERT @Child (bar, foo) VALUES (400, 4)
    INSERT @Child (bar, foo) VALUES (500, NULL)
    
    --"positive" checks
    SELECT -- multiple "2" = FAIL without DISTINCT
        P.*
    FROM
        @Parent P JOIN @Child C ON P.foo = C.foo
    
    SELECT -- correct
        P.*
    FROM
        @Parent P
    WHERE
        P.foo IN (SELECT c.foo FROM @Child C)
    
    SELECT -- correct
        P.*
    FROM
        @Parent P
    WHERE
        EXISTS (SELECT * FROM @Child C WHERE P.foo = C.foo)
    
    --"negative" checks
    SELECT -- correct
        P.*
    FROM
        @Parent P LEFT JOIN @Child C ON P.foo = C.foo
    WHERE
        C.foo IS NULL
    
    SELECT -- no rows = FAIL
        P.*
    FROM
        @Parent P
    WHERE
        P.foo NOT IN (SELECT c.foo FROM @Child C)
    
    SELECT -- correct
        P.*
    FROM
        @Parent P
    WHERE
        NOT EXISTS (SELECT * FROM @Child C WHERE P.foo = C.foo)
    

    Note: with EXISTS, the SELECT in the subquery is irrelevant as mentioned in ANSI 92 standard...

    NOT EXISTS (SELECT * FROM @Child C WHERE P.foo = C.foo)
    NOT EXISTS (SELECT NULL FROM @Child C WHERE P.foo = C.foo)
    NOT EXISTS (SELECT 1 FROM @Child C WHERE P.foo = C.foo)
    NOT EXISTS (SELECT 1/0 FROM @Child C WHERE P.foo = C.foo)
    

提交回复
热议问题