HOWTO · MySQL

MySQL 再帰クエリ

このガイドでは、MySQL の再帰クエリについて学習します。

このページの内容

このガイドでは、MySQL の recursive クエリについて学習します。 このガイドでは、SQL で recursive クエリを作成する方法とその仕組みについて説明し、理解を深めます。

MySQL 再帰 クエリ

SQL の recursive クエリはサブクエリです。 名前が示すように、再帰的に機能します。 これには、基本ケース、ユーザー定義名、および終了条件付きの再帰ケースがあります。

with [Recursive] CTE(user_defined name) AS
(
    SELECT query (Non Recursive query or the Base query)
    UNION
    SELECT query (recursive query using the name [with a termination condition])
)
SELECT * from CTE_name;

上記は recursive SQL クエリの疑似コードです。 より深く掘り下げてみましょう。

with 節

with [Recursive] CTE(user_defined name) AS

SQL の with 句は、SQL の Recursive キーワードと一緒に最初に使用されます。 次に、AS キーワードが使用され、その後にユーザー定義の名前である CTE が続きます。

このキーワードの構文は、クエリの基本ケースを構成します。

CTE は common table expression と呼ばれ、後で後続の SELECT ステートメントで使用するためにユーザーが定義した一時的な名前付き結果セットです。

ベースクエリ

SELECT query (Non Recursive query or the Base query)

これは、ベース クエリと呼ばれる 2つのクエリの最初のクエリです。 これは非再帰クエリであり、再帰が発生するベース入力がここで提供されます。

連合条項

UNION

Union 演算子は、最初と 2 番目のクエリをマージするために途中で使用されます。

再帰クエリ

SELECT query (recursive query using the name [with a termination condition])

これは、with 句を使用して以前に作成した CTE テーブルを提供する必要がある recursive クエリであり、また、true になると再帰を終了する終了条件も提供する必要があります。

上記の疑似コードに示すように、Base および Recursive クエリは括弧 () 内に記述されます。

SELECT * from CTE_name

このクエリは、この再帰手法を使用して作成されたテーブルを表示します。

MySQL で Recursive クエリを実装する

適切に実装して、このクエリの動作を理解しましょう。

with recursive number_printer AS
(
    SELECT 1 AS digit
    UNION
    SELECT digit+1 FROM number_printer WHERE digit<5
)
SELECT * FROM number_printer

数値プリンター

上の表は、プログラムの実行結果です。 これが実行された方法です。

クエリは、with 句と recursive キーワードを使用して開始し、CTE として print_number を使用しました。 コードを実行するとすぐに、プログラムはそれが再帰クエリであることを理解するため、基本ケースを探します。

ベース クエリでは、ベース ケースを 1 から開始しました。ここで使用されるエイリアスは digit です。 実行の最初の繰り返しでは、出力は基本クエリから返された結果になります。

初期レコードは、ベース クエリの出力になります。

基本クエリから返された結果は、再帰クエリの入力になります。 2 回目の反復では、再帰クエリは前のクエリからの出力データを使用し、終了条件をチェックします。

終了条件が満たされた場合、反復は停止します。 それ以外の場合は、3 番目の反復に入ります。 3 番目の反復では、2 番目の反復で返された出力を入力として使用します。

これは、再帰の発生に基づく唯一のロジックです。

3 番目の反復が実行され、この反復の結果の出力が 4 番目の反復の入力として使用されます。 次に、4 回目の繰り返しで、ベース クエリの出力とその入力が追加されます。

終了条件が満たされるまで、再帰的に発生し続けます。

ここでは、number_printer というテーブルが非常に重要です。 このクエリを再帰的にするには、テーブルを使用する必要があります。 クエリの終了は、WHERE 句を使用して終了条件を記述します。

ここで、再帰クエリに関する別の例を見てみましょう。

例 2: 階層

何らかの階層を持つ組織があるとします。 トップにマネージャーがいて、そのマネージャーの直属のマネージャーが 2 人いて、この 2 人のマネージャーのそれぞれに直属のマネージャーがいます。

これで、id、name、ManagerID などの列を持つ network というテーブルが作成されました。 これらはそれぞれ、従業員の ID、名前、およびマネージャー ID を定義します。

次の表に示します。

ネットワーク

上の表では、従業員の名前とマネージャー ID を取得しましたが、前述の階層に基づいて、これらのマネージャーにランクを適切に割り当てたいと考えています。 そのため、次のコードを使用します。

WITH RECURSIVE hierarchy AS
( SELECT id, name, 1 AS level FROM network WHERE id = 1
UNION
SELECT n.id, n.name, h.level+1 FROM hierarchy h
JOIN network n on h.id = n.ManagerID
)
SELECT * FROM hierarchy

上記の再帰クエリ コードは、私たちが望んでいた問題を解決します。 このコードが何をするのかを理解してみましょう。

With 句は構文に従って Recursive キーワードと一緒に使用され、ここでの CTE は hierarchy と名付けられています。

基本クエリでは、network テーブルから id と name を選択し、id が 1 に等しい値をフェッチします。 次に、値 AS level を整数 1 に設定します。

level は、階層内のマネージャーの位置を示すためにここで使用されます。

基本クエリはこれで完了です。 ここで、コードは UNION 句を使用して基本クエリを再帰クエリとマージします。

再帰クエリは、network テーブルから id と name を選択します。 ここでの n は network テーブルのエイリアスであり、このドット (.) がここで行うことは、その前に入力として指定した特定のテーブルからフェッチされる値を制限することです。

h は hierarchy テーブルのエイリアスであり、level+1 節は hierarchy テーブルから取得した整数値に 1 を追加することを保証します。

再帰クエリのこの部分は、network テーブルから name と id を取得し、整数値は hierarchy から取得され、1 が追加され、出力が level に保存されます。 . このクエリは、マネージャーのレベルを更新および定義します。

クエリの次の部分では、JOIN 句が使用されます。これは、デフォルト値で 内部結合 として機能します。 ここで、network テーブルの ManagerID は hierarchy テーブルの id と照合され、上記のクエリで内部結合されます。

ロジックは、マネージャー ID が ID と一致すると、マネージャーのレベルに 1 を追加することによって、そのエンティティーへのレベルが割り当てられるというものです。 このようにして、監督のランクが割り当てられます。

階層