sql >> Databáze >  >> RDS >> Sqlserver

Kdy použít EXCEPT na rozdíl od NOT EXISTS v Transact SQL?

EXCEPT zachází s NULL hodnoty jako odpovídající.

Tento dotaz:

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
        )

vrátí prázdnou sadu řádků.

Tento dotaz:

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
        )

vrátí

NULL
1

a tento:

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

vrátí:

1

Rekurzivní odkaz je také povolen v EXCEPT klauzule v rekurzivním CTE , i když se chová zvláštním způsobem:vrací vše kromě posledního řádku předchozí sady, ne všechno kromě celé předchozí sady:

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 Server vývojáři to asi zapomněli zakázat.



  1. Jednoduchá parametrizace a triviální plány — 3. část

  2. PLS-00428:V tomto příkazu SELECT se očekává klauzule INTO

  3. Vysvětlete podrobněji návrh výkonu JOIN vs. LEFT JOIN a WHERE

  4. ScaleGrid DBaaS rozšiřuje MySQL hostingové služby prostřednictvím AWS Cloud