Różnica między CTE a SubQuery?

Z tego postu Jak użyć ROW_NUMBER w poniższej procedurze?

Istnieją dwie wersje odpowiedzi, w których jedna używa SubQuery, a druga używa CTE do rozwiązania tego samego problemu.

Teraz, jaka jest zaleta używania CTE (Common Table Expression) nad Sub-query(tak więc, więcej czytelny co faktycznie robi zapytanie)

Jedyną zaletą korzystania z CTE nad sub select jest to, że w rzeczywistości mogę nazwać sub query. Czy są jakieś inne różnice między tymi dwoma kiedy CTE jest używany jako prosty (nie rekurencyjny) CTE?

Author: DineshDB, 2009-04-01

9 answers

W sub-query vs simple (non-recursive) wersje CTE są prawdopodobnie bardzo podobne. Będziesz musiał użyć profilera i rzeczywistego planu wykonania, aby zauważyć wszelkie różnice ,a to byłoby specyficzne dla Twojej konfiguracji (więc nie możemy podać pełnej odpowiedzi).

In general ; CTE może być użyte rekurencyjnie; zapytanie podrzędne nie może. To sprawia, że szczególnie dobrze nadają się do struktur drzewnych.

 82
Author: Marc Gravell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-01 19:21:09

Główną zaletą Common Table Expression (gdy nie używa się go do rekurencyjnych zapytań ) jest enkapsulacja, zamiast deklarować podzapytanie w każdym miejscu, w którym chcesz go użyć, możesz zdefiniować je raz, ale mieć do niego wiele odniesień.

To jednak nie oznacza, że jest ona wykonywana tylko raz(zgodnie z poprzednimi iteracjami tej odpowiedzi , dziękuję wszystkim, którzy skomentowali). Zapytanie zdecydowanie ma możliwość wielokrotnego wykonania, jeśli odwołuje się wiele razy; optymalizator zapytań ostatecznie podejmuje decyzję co do jak CTE powinno być zinterpretowane.

 74
Author: casperOne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:55:13

CTE's są najbardziej przydatne dla rekurencji:

WITH hier(cnt) AS (
        SELECT  1
        UNION ALL
        SELECT  cnt + 1
        FROM    hier
        WHERE   cnt < @n
        )
SELECT  cnt
FROM    hier

Zwróci @n wiersze (do 101). Przydatne do kalendarzy, atrapy wierszy itp.

Są też bardziej czytelne (moim zdaniem).

Poza Tym, CTE i subqueries są identyczne.

 15
Author: Quassnoi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-16 14:05:39

Jedna różnica, która nie została wymieniona, to pojedynczy CTE może być odwołany w kilku częściach Unii

 9
Author: user340140,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-19 01:59:42

O ile czegoś nie przeoczyłem, równie łatwo można nazwać zapytania CTE i subqueries.

Myślę, że główną różnicą jest czytelność (uważam, że CTE jest bardziej czytelne, ponieważ definiuje subquery z przodu, a nie w środku).

A jeśli potrzebujesz zrobić coś z rekurencją, będziesz miał mały problem z zrobieniem tego z subquery ;)

 8
Author: AlexCuse,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-01 19:22:10

Dodawanie do odpowiedzi innych, jeśli masz jedno i to samo zapytanie podrzędne używane kilka razy, możesz zastąpić wszystkie te zapytania jednym CTE. Pozwala to na lepsze wykorzystanie kodu.

 5
Author: A-K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-23 21:48:35

Ważnym faktem, o którym nikt nie wspomniał, jest to, że (przynajmniej w postgres) CTE są płotami optymalizacyjnymi:

Https://blog.2ndquadrant.com/postgresql-ctes-are-optimization-fences/

Oznacza to, że będą one traktowane jako własne zapytania atomowe, a nie złożone w cały plan zapytań. Brakuje mi Wiedzy, aby dać lepsze wyjaśnienie, ale powinieneś sprawdzić semantykę dla wersji sql używasz; dla zaawansowanych użytkowników, jest w stanie stworzyć ogrodzenie optymalizacyjne może pomóc w wydajności, jeśli jesteś ekspertem w kontrolowaniu planisty zapytań; w 99% przypadków należy jednak unikać prób mówienia planiście zapytań, co ma robić, ponieważ to, co myślisz, że będzie szybsze, jest prawdopodobnie gorsze niż to, co myśli, że będzie szybsze. :-)

 5
Author: Ajax,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-03 23:55:28

Jedną z rzeczy, które musisz zrozumieć, jest to, że w starszych wersjach SQL Server (tak wiele osób nadal musi obsługiwać bazy danych SQL Server 2000), CTE nie są dozwolone, a następnie tabela pochodna jest najlepszym rozwiązaniem.

 4
Author: HLGEM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-26 16:18:20

HINT: (MAXRECURSION n)

Można ograniczyć liczbę poziomów rekurencji dozwolonych dla określonego polecenie za pomocą podpowiedzi MAXRECURSION i wartości pomiędzy 0 oraz 32,767 w klauzuli OPTION

Na przykład, możesz spróbować:

OPTION 
      (MAXRECURSION 150)

GO
 2
Author: Basic_,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-31 11:53:23