Documentation Home
MySQL 8.0 リファレンスマニュアル
Download this Manual
PDF (US Ltr) - 36.1Mb
PDF (A4) - 36.2Mb


このページは機械翻訳したものです。

13.2.11.9 ラテラル導出テーブル

導出テーブルは、通常、同じ FROM 句内の前述のテーブルのカラムを参照 (依存) することはできません。 MySQL 8.0.14 では、導出テーブルを横導出テーブルとして定義して、このような参照が許可されるように指定できます。

非ラテラル導出テーブルは、セクション13.2.11.8「導出テーブル」 で説明されている構文を使用して指定します。 ラテラル導出テーブルの構文は、導出テーブルの指定の前にキーワード LATERAL が指定されている点を除き、非ラテラル導出テーブルの構文と同じです。 LATERAL キーワードは、ラテラル導出テーブルとして使用される各テーブルの前に指定する必要があります。

ラテラル導出テーブルには、次の制限事項があります:

  • ラテラル導出テーブルは、カンマで区切られたテーブルのリストまたは結合指定 (JOIN, INNER JOIN, CROSS JOIN, LEFT [OUTER] JOIN または RIGHT [OUTER] JOIN) のいずれかで、FROM 句でのみ使用できます。

  • ラテラル導出テーブルが結合句の右オペランドにあり、左オペランドへの参照が含まれている場合、結合操作は INNER JOINCROSS JOIN または LEFT [OUTER] JOIN である必要があります。

    テーブルが左オペランドにあり、右オペランドへの参照が含まれている場合、結合操作は INNER JOINCROSS JOIN または RIGHT [OUTER] JOIN である必要があります。

  • ラテラル導出テーブルが集計関数を参照する場合、関数集計クエリーを、ラテラル導出テーブルが発生する FROM 句を所有するクエリーにすることはできません。

  • SQL 標準に従って、テーブル関数には暗黙的な LATERAL があるため、8.0.14 より前の MySQL 8.0 バージョンと同様に動作します。 ただし、標準に従って、LATERAL ワードは暗黙的であっても JSON_TABLE() の前には許可されません。

次の説明では、潜在的導出テーブルによって、非潜在的導出テーブルで実行できない特定の SQL 操作や、より効率的な回避策を必要とする特定の SQL 操作がどのように行われるかを示します。

この問題を解決するとします: 営業部隊内の個人のテーブル (各行に販売部隊のメンバーが記述されている) と、すべての売上のテーブル (各行に販売が記述されている) があるとします: 営業担当、顧客、金額、日付) は、各営業担当の最大販売の規模と顧客を決定します。 この問題には 2 つの方法があります。

問題を解決する最初のアプローチ: 各営業担当について、最大販売サイズを計算し、この最大値を指定した顧客も検索します。 MySQL では、次のように実行できます:

Press CTRL+C to copy
SELECT salesperson.name, -- find maximum sale size for this salesperson (SELECT MAX(amount) AS amount FROM all_sales WHERE all_sales.salesperson_id = salesperson.id) AS amount, -- find customer for this maximum size (SELECT customer_name FROM all_sales WHERE all_sales.salesperson_id = salesperson.id AND all_sales.amount = -- find maximum size, again (SELECT MAX(amount) AS amount FROM all_sales WHERE all_sales.salesperson_id = salesperson.id)) AS customer_name FROM salesperson;

このクエリーでは、営業担当ごとに最大サイズが 2 回 (最初のサブクエリーで 1 回、2 回目で) 計算されるため、非効率的です。

次の変更されたクエリーに示すように、営業担当ごとに最大数を計算し、それを導出テーブルで「キャッシュ」することで、効率性向上を試みることができます:

Press CTRL+C to copy
SELECT salesperson.name, max_sale.amount, max_sale_customer.customer_name FROM salesperson, -- calculate maximum size, cache it in transient derived table max_sale (SELECT MAX(amount) AS amount FROM all_sales WHERE all_sales.salesperson_id = salesperson.id) AS max_sale, -- find customer, reusing cached maximum size (SELECT customer_name FROM all_sales WHERE all_sales.salesperson_id = salesperson.id AND all_sales.amount = -- the cached maximum size max_sale.amount) AS max_sale_customer;

ただし、導出テーブルは同じ FROM 句の他のテーブルに依存できないため、SQL-92 ではクエリーは無効です。 導出テーブルは、クエリー期間中は一定である必要があり、他の FROM 句テーブルのカラムへの参照は含まれません。 前述のとおり、クエリーでは次のエラーが生成されます:

Press CTRL+C to copy
ERROR 1054 (42S22): Unknown column 'salesperson.id' in 'where clause'

SQL:1999 では、導出テーブルの前に LATERAL キーワード (「この導出テーブルは左側の前のテーブルに依存しています」を意味する) がある場合、クエリーは有効になります:

Press CTRL+C to copy
SELECT salesperson.name, max_sale.amount, max_sale_customer.customer_name FROM salesperson, -- calculate maximum size, cache it in transient derived table max_sale LATERAL (SELECT MAX(amount) AS amount FROM all_sales WHERE all_sales.salesperson_id = salesperson.id) AS max_sale, -- find customer, reusing cached maximum size LATERAL (SELECT customer_name FROM all_sales WHERE all_sales.salesperson_id = salesperson.id AND all_sales.amount = -- the cached maximum size max_sale.amount) AS max_sale_customer;

ラテラル導出テーブルは定数である必要はなく、それが依存する前のテーブルの新しい行が最上位のクエリーによって処理されるたびに最新になります。

問題を解決するための第 2 のアプローチ: SELECT リストのサブクエリーが複数のカラムを返す可能性がある場合は、別の解決策を使用できます:

Press CTRL+C to copy
SELECT salesperson.name, -- find maximum size and customer at same time (SELECT amount, customer_name FROM all_sales WHERE all_sales.salesperson_id = salesperson.id ORDER BY amount DESC LIMIT 1) FROM salesperson;

これは効率的ですが、不正です。 このようなサブクエリーは単一のカラムのみを返すことができるため、機能しません:

Press CTRL+C to copy
ERROR 1241 (21000): Operand should contain 1 column(s)

クエリーをリライトするには、導出テーブルから複数のカラムを選択します:

Press CTRL+C to copy
SELECT salesperson.name, max_sale.amount, max_sale.customer_name FROM salesperson, -- find maximum size and customer at same time (SELECT amount, customer_name FROM all_sales WHERE all_sales.salesperson_id = salesperson.id ORDER BY amount DESC LIMIT 1) AS max_sale;

ただし、これも機能しません。 導出テーブルは salesperson テーブルに依存しているため、LATERAL なしで失敗します:

Press CTRL+C to copy
ERROR 1054 (42S22): Unknown column 'salesperson.id' in 'where clause'

LATERAL キーワードを追加すると、クエリーは有効になります:

Press CTRL+C to copy
SELECT salesperson.name, max_sale.amount, max_sale.customer_name FROM salesperson, -- find maximum size and customer at same time LATERAL (SELECT amount, customer_name FROM all_sales WHERE all_sales.salesperson_id = salesperson.id ORDER BY amount DESC LIMIT 1) AS max_sale;

つまり、LATERAL は、前述の 2 つのアプローチにおけるすべての欠点に対する効率的なソリューションです。