次の方法で共有


Fabric データ ウェアハウスの入れ子になった共通テーブル式 (CTE) (Transact-SQL)

適用対象:Microsoft Fabric SQL 分析エンドポイントと Warehouse

共通テーブル式 (CTE) を使用すると、通常複雑なクエリを再利用可能なブロックに分解することで、複雑なクエリを簡略化できます。

CTE には、 standardsequentialrecursivenested CTE の 4 種類があります。

  • 標準 CTE は、その定義内で別の CTE を参照または定義しません。
  • 入れ子になった CTE の定義には、別の CTE の定義が含まれます。
  • シーケンシャル CTE の定義は既存の CTE を参照できますが、別の CTE を定義することはできません。
  • 再帰 CTE は、その定義内でそれ自体を参照します。

Fabric Warehouse と SQL 分析エンドポイントは、どちらも standardsequential、および nested CTE (プレビュー) をサポートします。 Microsoft Fabric では標準 CTE とシーケンシャル CTE が一般提供されていますが、入れ子になった CTE は現在プレビュー機能です。

一般的なテーブル式の詳細については、「 WITH common_table_expression (Transact-SQL)」を参照してください。

Note

プレビュー期間中、入れ子になった CTE の作成は SQL Server Management Studio (SSMS) でのみサポートされます。 SSMS の Intellisense では、入れ子になった CTE 構文は認識されませんが、入れ子になった CTE の作成はブロックされません。 最適なエクスペリエンスを得るために、入れ子のレベルを 64 に制限します。

構文

WITH <NESTED_CTE_NAME_LEVEL1> [ (column_name , ...) ] AS
    (WITH <NESTED_CTE_NAME_LEVEL2> [ (column_name , ...) ] AS
        (
            ...
                WITH <NESTED_CTE_NAME_LEVELn-1> [ ( column_name , ...) ] AS
                (
                    WITH <NESTED_CTE_NAME_LEVELn> [ ( column_name , ...) ] AS
                    (
                        Standard_CTE_query_definition
                    )
                    <SELECT statement> -- Data source must include NESTED_CTE_NAME_LEVELn
                )
                <SELECT statement> -- Data source must include NESTED_CTE_NAME_LEVELn-1
            ...
        )
    <SELECT statement> -- Data source must include NESTED_CTE_NAME_LEVEL2
    )

入れ子になった CTE の作成と使用に関するガイドライン

標準の CTE の作成と使用に関するガイドラインに加えて、入れ子になった CTE に関する追加のガイドラインを次に示します。

  • 入れ子になった CTE は、SELECT ステートメントでのみ使用できます。 UPDATE、INSERT、または DELETE ステートメントでは使用できません。
  • 入れ子になった CTE の定義では、UPDATE、INSERT、または DELETE ステートメントは使用できません。
  • 同じ入れ子レベルの CTE 名を複製することはできません。
  • 入れ子になった CTE は、その直前の上位レベルにある入れ子になった CTE または順次 CTE にのみ表示されます。
  • データベース間クエリは、入れ子になった CTE 定義で許可されます。
  • クエリ ヒント (つまり OPTION 句) は、入れ子になった CTE の定義では使用できません。
  • 入れ子になった CTE は CREATE VIEW では使用できません。
  • 入れ子になった CTE の定義では、AS OF はサポートされていません。
  • 入れ子になった CTE は CTE サブクエリ定義でサポートされますが、一般的なサブクエリではサポートされません。

標準、シーケンシャル、および入れ子になった CTE の違い

-- Standard CTE
;WITH Standard_CTE AS (
    SELECT * FROM T1
)
SELECT * FROM Standard_CTE;

-- Sequential CTE
;WITH CTE1 AS (
    SELECT * FROM T1
),
CTE2 AS (SELECT * FROM CTE1),
CTE3 AS (SELECT * FROM CTE2)
SELECT * FROM CTE3

-- Nested CTE
;WITH OUTER_CTE AS (
    WITH INNER_CTE AS (
        SELECT * FROM T1
    )
    SELECT * FROM INNER_CTE
)
SELECT * FROM OUTER_CTE;

CTE の名前スコープは、そのスコープに制限されます

CTE 名は、異なる入れ子レベルで再利用できます。 同じ入れ子レベルの CTE 名を複製することはできません。 この例では、外部スコープと内部スコープの両方で cte1 名が使用されます。

;WITH
    cte1 AS (
        WITH
            inner_cte1_1 AS (
                SELECT * FROM NestedCTE_t1 WHERE c1 = 1
            ),
            inner_cte1_2 AS (
                SELECT * FROM inner_cte1_1 WHERE c2 = 1
            )
        SELECT * FROM inner_cte1_2
    ),
    cte2 AS (
        WITH
            cte1 AS (
                SELECT * FROM NestedCTE_t1 WHERE c3 = 1
            ),
            inner_cte2_2 AS (
                SELECT * FROM cte1 WHERE c4 = 1
            )
        SELECT * FROM inner_cte2_2
    )

共用体、共用体すべて、交差、および除く複雑な入れ子になった CTE

CREATE TABLE NestedCTE_t1 (
    c1 INT,
    c2 INT,
    c3 INT
);
GO

INSERT INTO NestedCTE_t1
VALUES (1, 1, 1);

INSERT INTO NestedCTE_t1
VALUES (2, 2, 2);

INSERT INTO NestedCTE_t1
VALUES (3, 3, 3);
GO

WITH
    outermost_cte_1 AS (
        WITH
            outer_cte_1 AS (
                WITH
                    inner_cte1_1 AS (
                        SELECT * FROM NestedCTE_t1 WHERE c1 = 1
                    ),
                    inner_cte1_2 AS (
                        SELECT * FROM inner_cte1_1
                        UNION SELECT * FROM inner_cte1_1
                    )
                SELECT * FROM inner_cte1_1
                UNION ALL SELECT * FROM inner_cte1_2
            ),
            outer_cte_2 AS (
                WITH
                    inner_cte2_1 AS (
                        SELECT * FROM NestedCTE_t1 WHERE c2 = 1
                        EXCEPT SELECT * FROM outer_cte_1
                    ),
                    inner_cte2_2 AS (
                        SELECT * FROM NestedCTE_t1 WHERE c3 = 1
                        UNION SELECT * FROM inner_cte2_1
                    )
                SELECT * FROM inner_cte2_1
                UNION ALL SELECT * FROM outer_cte_1
            )
        SELECT * FROM outer_cte_1
        INTERSECT SELECT * FROM outer_cte_2
    ),
    outermost_cte_2 AS (
        SELECT * FROM outermost_cte_1
        UNION SELECT * FROM outermost_cte_1
    )
SELECT * FROM outermost_cte_1
UNION ALL SELECT * FROM outermost_cte_2;

入れ子になった CTE は CTE サブクエリ定義ではサポートされていますが、一般的なサブクエリではサポートされていません

このクエリは、次のエラーで失敗します。 Msg 156, Level 15, State 1, Line 3. Incorrect syntax near the keyword 'WITH'.

SELECT * FROM
(
    WITH
        inner_cte1_1 AS (SELECT * FROM NestedCTE_t1 WHERE c1 = 1),
        inner_cte1_2 AS  (SELECT * FROM inner_cte1_1)
    SELECT * FROM inner_cte1_2
) AS subq1;

CTE への参照は、そのスコープを超えることはできません

このクエリは、次のエラーで失敗します。 Msg 208, Level 16, State 1, Line 1. Invalid object name 'inner_cte1_1'.

;WITH
    outer_cte_1 AS (
        WITH
            inner_cte1_1 AS (
                SELECT * FROM NestedCTE_t1 WHERE c1 = 1
            ),
            inner_cte1_2 AS (
                SELECT * FROM inner_cte1_1 WHERE c2 = 1
            )
        SELECT * FROM inner_cte1_2
    ),
    outer_cte_2 AS (
        WITH inner_cte2_1 AS (
            SELECT * FROM NestedCTE_t1 WHERE c3 = 1
        )
        SELECT
            tmp2.*
        FROM
            inner_cte1_1 AS tmp1,
            inner_cte2_1 AS tmp2
        WHERE
            tmp1.c4 = tmp2.c4
    )
SELECT * FROM outer_cte_2;