共通テーブル式を使用した再帰クエリ
9629 ワード
http://msdn.microsoft.com/zh-cn/library/ms186243.aspx
共通テーブル式を使用した再帰クエリ
SQL Server 2008 R2
その他のバージョン
0(合計1)本明細書の評価に役立つ−このテーマを評価
共通テーブル式(CTE)は、それ自体を参照して再帰CTEを作成できるという重要な利点を有する.再帰CTEは、完全な結果セットを取得するまで、初期CTEを繰り返し実行してデータのサブセットを返す共通テーブル式である.
クエリが再帰CTEを参照する場合、それは再帰クエリと呼ばれます.再帰クエリは、通常、階層化されたデータを返すために使用されます.たとえば、親製品に1つ以上のコンポーネントがあり、そのコンポーネントにサブコンポーネント、または他の親製品のコンポーネントがある場合がある組織図の従業員またはBOMスキーマのデータを表示します.
再帰CTEは、SELECT、INSERT、UPDATE、DELETE、またはCREATE VIEW文で再帰クエリを実行するために必要なコードを大幅に簡略化することができる.SQL Serverの以前のバージョンでは、再帰クエリは通常、一時テーブル、カーソル、論理を使用して再帰ステップフローを制御する必要があります.共通テーブル式の詳細については、共通テーブル式の使用を参照してください.
再帰CTEの構造
Transact−SQLにおける再帰CTEの構造は他のプログラミング言語における再帰ルーチンと類似している.他の言語の再帰ルーチンはスカラー値を返すが、再帰CTEは複数行を返すことができる.
再帰CTEは、次の3つの要素から構成されています.ルーチンの呼び出し.再帰CTEの第1の呼び出しは、ユニオンALL、ユニオン、EXCEPTまたはINTERSECT演算子によって結合された1つまたは複数のCTE_を含むquery_definitions.これらのクエリ定義はCTE構造のベンチマーク結果セットを形成するため、「ポイントメンバーの位置決め」と呼ばれます.CTE_query_definitionsは、CTE自体を参照しない限り、位置決めポイントメンバーと見なされます.すべてのロケータメンバークエリー定義は、最初の再帰メンバー定義の前に配置する必要があります.また、UNIOALL演算子を使用して最後のロケータメンバーと最初の再帰メンバーを結合する必要があります. ルーチンの再帰呼び出し.再帰的呼び出しは、CTE自体を参照するUNIOALL演算子によって結合された1つまたは複数のCTE_を含むquery_definitions.これらのクエリー定義は「再帰メンバー」と呼ばれます. 検査を終了します.チェックの終了は暗黙的です.前の呼び出しでローが返されなかった場合、再帰は停止します.
注意
再帰CTEの組み合わせが正しくない場合、無限ループを引き起こす可能性があります.たとえば、再帰メンバー・クエリー定義が親カラムと子カラムに同じ値を返す場合、無限ループが発生します.再帰クエリの結果をテストするときは、INSERT、UPDATE、DELETEまたはSELECT文のOPTION句でMAXRECURSIONプロンプトと0~32767の値を使用することで、特定の文で許可される再帰級数を制限できます.詳細については、クエリーヒント(Transact-SQL)およびWITH common_table_expression (Transact-SQL)を参照してください.
疑似コードと意味
再帰CTE構造は、少なくとも1つの位置決めポイントメンバーと1つの再帰メンバーを含む必要があります.次の疑似コードは、1つの位置決めポイントメンバーと1つの再帰メンバーを含む単純な再帰CTEのコンポーネントを示す.
WITH cte_name ( column_name [,...n] )
AS
(
CTE_query_definition –- Anchor member is defined.
UNION ALL
CTE_query_definition –- Recursive member is defined referencing cte_name.
)
-- Statement using the CTE
SELECT *
FROM cte_name
再帰的に実行される意味は次のとおりです. CTE式は、位置決めポイントメンバーと再帰メンバーに分割されます. 位置決めポイントメンバーを実行し、最初の呼び出しまたは基準結果セット(T 0)を作成します. 再帰メンバーを実行し、Tiを入力とし、Ti+1を出力とする. は、空のセットに戻るまで手順3を繰り返します. は結果セットを返します.これは、T 0~Tnに対してUNIOALLを実行した結果である.
例
次の例では、Adventure Works Cycles社の従業員の階層リスト(最上位従業員から)を返すことで、再帰CTE構造の意味を示します.例の後にコード実行の演習があります.
Transact-SQL
Transact-SQL
サンプルコードの練習再帰CTE DirectReportsは、位置決めポイントメンバーと再帰メンバーを定義します. 位置決めポイントメンバーは、基準結果セットT 0を返す.これが会社の最上位の従業員です.つまり、マネージャーに報告しない従業員です.次は、アンカーポイントメンバーが返す結果セットです.
再帰メンバーは、ロケーションポイントメンバー結果セットの従業員の直接部下を返します.これは、EmployeeテーブルとDirectReports CTEとの間で結合動作を実行することによって得られる.今回,CTE自身の参照に対して再帰呼び出しが確立された.CTE DirectReportsの従業員を入力(Ti)として利用し、結合(MyEmployees.ManagerID=DirectReports.EmployeeID)を出力(Ti)としてマネージャーの従業員に返す.これにより、再帰メンバーの最初の反復は、次の結果セットを返します.
再帰メンバーの再アクティブ化を繰り返します.再帰メンバーの2回目の反復は、ステップ3の1行結果セット(EmployeeID 273を含む)を入力値として使用し、次の結果セットを返します.
再帰メンバーの3回目の反復は、上の結果セットを入力値として使用し、次の結果セットを返します.
が実行中のクエリが返す最終結果セットは、ロケーションポイントメンバーと再帰メンバーが生成したすべての結果セットのセットです.次の例では、サンプルが返す完全な結果セットを示します.
参照
リファレンス
WITH common_table_expression (Transact-SQL)
クエリーヒント(Transact-SQL)
INSERT (Transact-SQL)
UPDATE (Transact-SQL)
DELETE (Transact-SQL)
EXCEPTとINTERSECT(Transact-SQL)
共通テーブル式を使用した再帰クエリ
SQL Server 2008 R2
その他のバージョン
0(合計1)本明細書の評価に役立つ−このテーマを評価
共通テーブル式(CTE)は、それ自体を参照して再帰CTEを作成できるという重要な利点を有する.再帰CTEは、完全な結果セットを取得するまで、初期CTEを繰り返し実行してデータのサブセットを返す共通テーブル式である.
クエリが再帰CTEを参照する場合、それは再帰クエリと呼ばれます.再帰クエリは、通常、階層化されたデータを返すために使用されます.たとえば、親製品に1つ以上のコンポーネントがあり、そのコンポーネントにサブコンポーネント、または他の親製品のコンポーネントがある場合がある組織図の従業員またはBOMスキーマのデータを表示します.
再帰CTEは、SELECT、INSERT、UPDATE、DELETE、またはCREATE VIEW文で再帰クエリを実行するために必要なコードを大幅に簡略化することができる.SQL Serverの以前のバージョンでは、再帰クエリは通常、一時テーブル、カーソル、論理を使用して再帰ステップフローを制御する必要があります.共通テーブル式の詳細については、共通テーブル式の使用を参照してください.
再帰CTEの構造
Transact−SQLにおける再帰CTEの構造は他のプログラミング言語における再帰ルーチンと類似している.他の言語の再帰ルーチンはスカラー値を返すが、再帰CTEは複数行を返すことができる.
再帰CTEは、次の3つの要素から構成されています.
注意
再帰CTEの組み合わせが正しくない場合、無限ループを引き起こす可能性があります.たとえば、再帰メンバー・クエリー定義が親カラムと子カラムに同じ値を返す場合、無限ループが発生します.再帰クエリの結果をテストするときは、INSERT、UPDATE、DELETEまたはSELECT文のOPTION句でMAXRECURSIONプロンプトと0~32767の値を使用することで、特定の文で許可される再帰級数を制限できます.詳細については、クエリーヒント(Transact-SQL)およびWITH common_table_expression (Transact-SQL)を参照してください.
疑似コードと意味
再帰CTE構造は、少なくとも1つの位置決めポイントメンバーと1つの再帰メンバーを含む必要があります.次の疑似コードは、1つの位置決めポイントメンバーと1つの再帰メンバーを含む単純な再帰CTEのコンポーネントを示す.
WITH cte_name ( column_name [,...n] )
AS
(
CTE_query_definition –- Anchor member is defined.
UNION ALL
CTE_query_definition –- Recursive member is defined referencing cte_name.
)
-- Statement using the CTE
SELECT *
FROM cte_name
再帰的に実行される意味は次のとおりです.
例
次の例では、Adventure Works Cycles社の従業員の階層リスト(最上位従業員から)を返すことで、再帰CTE構造の意味を示します.例の後にコード実行の演習があります.
Transact-SQL
-- Create an Employee table.
CREATE TABLE dbo.MyEmployees
(
EmployeeID smallint NOT NULL,
FirstName nvarchar(30) NOT NULL,
LastName nvarchar(40) NOT NULL,
Title nvarchar(50) NOT NULL,
DeptID smallint NOT NULL,
ManagerID int NULL,
CONSTRAINT PK_EmployeeID PRIMARY KEY CLUSTERED (EmployeeID ASC)
);
-- Populate the table with values.
INSERT INTO dbo.MyEmployees VALUES
(1, N'Ken', N'Sánchez', N'Chief Executive Officer',16,NULL)
,(273, N'Brian', N'Welcker', N'Vice President of Sales',3,1)
,(274, N'Stephen', N'Jiang', N'North American Sales Manager',3,273)
,(275, N'Michael', N'Blythe', N'Sales Representative',3,274)
,(276, N'Linda', N'Mitchell', N'Sales Representative',3,274)
,(285, N'Syed', N'Abbas', N'Pacific Sales Manager',3,273)
,(286, N'Lynn', N'Tsoflias', N'Sales Representative',3,285)
,(16, N'David',N'Bradley', N'Marketing Manager', 4, 273)
,(23, N'Mary', N'Gibson', N'Marketing Specialist', 4, 16);
Transact-SQL
USE AdventureWorks2008R2;
GO
WITH DirectReports (ManagerID, EmployeeID, Title, DeptID, Level)
AS
(
-- Anchor member definition
SELECT e.ManagerID, e.EmployeeID, e.Title, edh.DepartmentID,
0 AS Level
FROM dbo.MyEmployees AS e
INNER JOIN HumanResources.EmployeeDepartmentHistory AS edh
ON e.EmployeeID = edh.BusinessEntityID AND edh.EndDate IS NULL
WHERE ManagerID IS NULL
UNION ALL
-- Recursive member definition
SELECT e.ManagerID, e.EmployeeID, e.Title, edh.DepartmentID,
Level + 1
FROM dbo.MyEmployees AS e
INNER JOIN HumanResources.EmployeeDepartmentHistory AS edh
ON e.EmployeeID = edh.BusinessEntityID AND edh.EndDate IS NULL
INNER JOIN DirectReports AS d
ON e.ManagerID = d.EmployeeID
)
-- Statement that executes the CTE
SELECT ManagerID, EmployeeID, Title, DeptID, Level
FROM DirectReports
INNER JOIN HumanResources.Department AS dp
ON DirectReports.DeptID = dp.DepartmentID
WHERE dp.GroupName = N'Sales and Marketing' OR Level = 0;
GO
サンプルコードの練習
ManagerID EmployeeID Title Level
--------- ---------- ----------------------------- ------
NULL 1 Chief Executive Officer 0
ManagerID EmployeeID Title Level
--------- ---------- ----------------------------- ------
1 273 Vice President of Sales 1
ManagerID EmployeeID Title Level
--------- ---------- ----------------------------- ------
273 16 Marketing Manager 2
273 274 North American Sales Manager 2
273 285 Pacific Sales Manager 2
再帰メンバーの3回目の反復は、上の結果セットを入力値として使用し、次の結果セットを返します.
ManagerID EmployeeID Title Level
--------- ---------- ----------------------------- ------
16 23 Marketing Specialist 3
274 275 Sales Representative 3
274 276 Sales Representative 3
285 286 Sales Representative 3
ManagerID EmployeeID Title Level
--------- ---------- ----------------------------- ------
NULL 1 Chief Executive Officer 0
1 273 Vice President of Sales 1
273 16 Marketing Manager 2
273 274 North American Sales Manager 2
273 285 Pacific Sales Manager 2
16 23 Marketing Specialist 3
274 275 Sales Representative 3
274 276 Sales Representative 3
285 286 Sales Representative 3
参照
リファレンス
WITH common_table_expression (Transact-SQL)
クエリーヒント(Transact-SQL)
INSERT (Transact-SQL)
UPDATE (Transact-SQL)
DELETE (Transact-SQL)
EXCEPTとINTERSECT(Transact-SQL)