Rechercher dans le manuel MySQL

13.2.11.9 Lateral Derived Tables

A derived table cannot normally refer to (depend on) columns of preceding tables in the same FROM clause. As of MySQL 8.0.14, a derived table may be defined as a lateral derived table to specify that such references are permitted.

Nonlateral derived tables are specified using the syntax discussed in Section 13.2.11.8, “Derived Tables”. The syntax for a lateral derived table is the same as for a nonlateral derived table except that the keyword LATERAL is specified before the derived table specification. The LATERAL keyword must precede each table to be used as a lateral derived table.

Lateral derived tables are subject to these restrictions:

  • A lateral derived table can occur only in a FROM clause, either in a list of tables separated with commas or in a join specification (JOIN, INNER JOIN, CROSS JOIN, LEFT [OUTER] JOIN, or RIGHT [OUTER] JOIN).

  • If a lateral derived table is in the right operand of a join clause and contains a reference to the left operand, the join operation must be an INNER JOIN, CROSS JOIN, or LEFT [OUTER] JOIN.

    If the table is in the left operand and contains a reference to the right operand, the join operation must be an INNER JOIN, CROSS JOIN, or RIGHT [OUTER] JOIN.

  • If a lateral derived table references an aggregate function, the function's aggregation query cannot be the one that owns the FROM clause in which the lateral derived table occurs.

  • Per the SQL standard, a table function has an implicit LATERAL, so it behaves as in MySQL 8.0 versions prior to 8.0.14. However, per the standard, the LATERAL word is not allowed before JSON_TABLE(), even though it is implicit.

The following discussion shows how lateral derived tables make possible certain SQL operations that cannot be done with nonlateral derived tables or that require less-efficient workarounds.

Suppose that we want to solve this problem: Given a table of people in a sales force (where each row describes a member of the sales force), and a table of all sales (where each row describes a sale: salesperson, customer, amount, date), determine the size and customer of the largest sale for each salesperson. This problem can be approached two ways.

First approach to solving the problem: For each salesperson, calculate the maximum sale size, and also find the customer who provided this maximum. In MySQL, that can be done like this:

  1.   salesperson.name,
  2.   -- find maximum sale size for this salesperson
  3.   (SELECT MAX(amount) AS amount
  4.     FROM all_sales
  5.     WHERE all_sales.salesperson_id = salesperson.id)
  6.   AS amount,
  7.   -- find customer for this maximum size
  8.   (SELECT customer_name
  9.     FROM all_sales
  10.     WHERE all_sales.salesperson_id = salesperson.id
  11.     AND all_sales.amount =
  12.          -- find maximum size, again
  13.          (SELECT MAX(amount) AS amount
  14.            FROM all_sales
  15.            WHERE all_sales.salesperson_id = salesperson.id))
  16.   AS customer_name
  17.   salesperson;

That query is inefficient because it calculates the maximum size twice per salesperson (once in the first subquery and once in the second).

We can try to achieve an efficiency gain by calculating the maximum once per salesperson and caching it in a derived table, as shown by this modified query:

  1.   salesperson.name,
  2.   max_sale.amount,
  3.   max_sale_customer.customer_name
  4.   salesperson,
  5.   -- calculate maximum size, cache it in transient derived table max_sale
  6.   (SELECT MAX(amount) AS amount
  7.     FROM all_sales
  8.     WHERE all_sales.salesperson_id = salesperson.id)
  9.   AS max_sale,
  10.   -- find customer, reusing cached maximum size
  11.   (SELECT customer_name
  12.     FROM all_sales
  13.     WHERE all_sales.salesperson_id = salesperson.id
  14.     AND all_sales.amount =
  15.         -- the cached maximum size
  16.         max_sale.amount)
  17.   AS max_sale_customer;

However, the query is illegal in SQL-92 because derived tables cannot depend on other tables in the same FROM clause. Derived tables must be constant over the query's duration, not contain references to columns of other FROM clause tables. As written, the query produces this error:

ERROR 1054 (42S22): Unknown column 'salesperson.id' in 'where clause'

In SQL:1999, the query becomes legal if the derived tables are preceded by the LATERAL keyword (which means this derived table depends on previous tables on its left side):

  1.   salesperson.name,
  2.   max_sale.amount,
  3.   max_sale_customer.customer_name
  4.   salesperson,
  5.   -- calculate maximum size, cache it in transient derived table max_sale
  6.   LATERAL
  7.   (SELECT MAX(amount) AS amount
  8.     FROM all_sales
  9.     WHERE all_sales.salesperson_id = salesperson.id)
  10.   AS max_sale,
  11.   -- find customer, reusing cached maximum size
  12.   LATERAL
  13.   (SELECT customer_name
  14.     FROM all_sales
  15.     WHERE all_sales.salesperson_id = salesperson.id
  16.     AND all_sales.amount =
  17.         -- the cached maximum size
  18.         max_sale.amount)
  19.   AS max_sale_customer;

A lateral derived table need not be constant and is brought up to date each time a new row from a preceding table on which it depends is processed by the top query.

Second approach to solving the problem: A different solution could be used if a subquery in the SELECT list could return multiple columns:

  1.   salesperson.name,
  2.   -- find maximum size and customer at same time
  3.   (SELECT amount, customer_name
  4.     FROM all_sales
  5.     WHERE all_sales.salesperson_id = salesperson.id
  6.     ORDER BY amount DESC LIMIT 1)
  7.   salesperson;

That is efficient but illegal. It does not work because such subqueries can return only a single column:

ERROR 1241 (21000): Operand should contain 1 column(s)

One attempt at rewriting the query is to select multiple columns from a derived table:

  1.   salesperson.name,
  2.   max_sale.amount,
  3.   max_sale.customer_name
  4.   salesperson,
  5.   -- find maximum size and customer at same time
  6.   (SELECT amount, customer_name
  7.     FROM all_sales
  8.     WHERE all_sales.salesperson_id = salesperson.id
  9.     ORDER BY amount DESC LIMIT 1)
  10.   AS max_sale;

However, that also does not work. The derived table is dependent on the salesperson table and thus fails without LATERAL:

ERROR 1054 (42S22): Unknown column 'salesperson.id' in 'where clause'

Adding the LATERAL keyword makes the query legal:

  1.   salesperson.name,
  2.   max_sale.amount,
  3.   max_sale.customer_name
  4.   salesperson,
  5.   -- find maximum size and customer at same time
  6.   LATERAL
  7.   (SELECT amount, customer_name
  8.     FROM all_sales
  9.     WHERE all_sales.salesperson_id = salesperson.id
  10.     ORDER BY amount DESC LIMIT 1)
  11.   AS max_sale;

In short, LATERAL is the efficient solution to all drawbacks in the two approaches just discussed.


Suchen Sie im MySQL-Handbuch

Deutsche Übersetzung

Sie haben gebeten, diese Seite auf Deutsch zu besuchen. Momentan ist nur die Oberfläche übersetzt, aber noch nicht der gesamte Inhalt.

Wenn Sie mir bei Übersetzungen helfen wollen, ist Ihr Beitrag willkommen. Alles, was Sie tun müssen, ist, sich auf der Website zu registrieren und mir eine Nachricht zu schicken, in der Sie gebeten werden, Sie der Gruppe der Übersetzer hinzuzufügen, die Ihnen die Möglichkeit gibt, die gewünschten Seiten zu übersetzen. Ein Link am Ende jeder übersetzten Seite zeigt an, dass Sie der Übersetzer sind und einen Link zu Ihrem Profil haben.

Vielen Dank im Voraus.

Dokument erstellt 26/06/2006, zuletzt geändert 26/10/2018
Quelle des gedruckten Dokuments:https://www.gaudry.be/de/mysql-rf-lateral-derived-tables.html

Die Infobro ist eine persönliche Seite, deren Inhalt in meiner alleinigen Verantwortung liegt. Der Text ist unter der CreativeCommons-Lizenz (BY-NC-SA) verfügbar. Weitere Informationen auf die Nutzungsbedingungen und dem Autor.

Referenzen

  1. Zeigen Sie - html-Dokument Sprache des Dokuments:en Manuel MySQL : https://dev.mysql.com/

Diese Verweise und Links verweisen auf Dokumente, die während des Schreibens dieser Seite konsultiert wurden, oder die zusätzliche Informationen liefern können, aber die Autoren dieser Quellen können nicht für den Inhalt dieser Seite verantwortlich gemacht werden.
Der Autor Diese Website ist allein dafür verantwortlich, wie die verschiedenen Konzepte und Freiheiten, die mit den Nachschlagewerken gemacht werden, hier dargestellt werden. Denken Sie daran, dass Sie mehrere Quellinformationen austauschen müssen, um das Risiko von Fehlern zu reduzieren.

Inhaltsverzeichnis Haut