简体   繁体   English

MySQL 中的 LATERAL 语法 - 是否只是说“左表”首先执行以便下一个可以引用它?

[英]LATERAL syntax in MySQL - Is it just to say that "the left table" is executed first so that the next one can reference it?

What does " A derived table cannot contain references to other tables of the same SELECT " mean? 派生表不能包含对同一 SELECT 的其他表的引用”是什么意思? I looked it up in the MySQL documentation我在 MySQL 文档中查找了它

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;

A derived table cannot contain references to other tables of the same SELECT (use a LATERAL derived table for that; see Section 13.2.11.9, “Lateral Derived Tables”)派生表不能包含对同一 SELECT 的其他表的引用(为此使用 LATERAL 派生表;请参阅第 13.2.11.9 节,“横向派生表”)

The key to understanding this is in the manual you have read:理解这一点的关键在于您已阅读的手册:

Derived tables must be constant over the query's duration, not contain references to columns of other FROM clause tables.派生表在查询期间必须保持不变,不包含对其他 FROM 子句表的列的引用。

That is, think of the derived table as running at the initial time of the query, before any rows from the joined tables have been read.也就是说,将派生表视为在查询的初始时间运行,在连接表中的任何行被读取之前。 If the derived table subquery includes any references to joined tables, then the result of the derived table would depend on data read from those tables.如果派生表子查询包括对连接表的任何引用,则派生表的结果将取决于从这些表中读取的数据。 Can conflicts with the requirement that a derived table be constant.可能与派生表为常量的要求相冲突。

LATERAL changes that. LATERAL改变了这一点。 It ensures that the derived table is evaluated later, after the query begins to read rows from the joined tables.它确保在查询开始从联接表中读取行之后,稍后评估派生表。

PS: The comment from jarlh above is not strictly correct. PS:上面 jarlh 的评论并不完全正确。 It is recommended for other reasons to use explicit JOIN syntax (eg it supports outer joins and so on), but it's not required for the sake of LATERAL .出于其他原因,建议使用显式JOIN语法(例如,它支持外连接等),但对于LATERAL而言,它不是必需的。

The documentation ( here ) attempts to explain that if you start with a correlated subquery inside the select list then it IS possible to refer to the table in the from clause eg:文档( 此处)试图解释,如果您从select listcorrelated subquery开始,则可以在from clause中引用该表,例如:

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
FROM
  salesperson;

In the query above you can see that the from table is salesperson but in the correlated subquery you CAN also refer to salesperson .在上面的查询中,您可以看到 from 表是salesperson ,但在correlated subquery中,您也可以引用salesperson The correlation is that the subquery is being executed row by row through the resultset, with each iteration of that subquery using the salesperson.id as input to the where clause. correlation是子查询通过结果集逐行执行,该子查询的每次迭代都使用salesperson.id作为 where 子句的输入。 (By the way, this "row by row" effect is often why correlated subqueries can be a cause of slowness in queries.) (顺便说一下,这种“逐行”效应通常是为什么correlated subqueries会导致查询速度变慢。)

However it is not permitted in traditional derived tables , found in the from clause , to use a correlation like the one seen above.但是,在from clause中的传统derived tables中,不允许使用上述correlation So the example below will fail because it tries to use a correlation to salesperson that isn't allowed:因此,下面的示例将失败,因为它尝试使用不允许的与销售人员correlation

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
  AS max_sale_customer;

As the documentation states this will result in an error:正如文档所述,这将导致错误:

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

BUT , with the addition of support for LATERAL it is possible to to replace correlated subqueries that we once used in the select clause with lateral subqueries as these DO support the ability to refer to other tables referenced in the from clause .但是,通过增加对LATERAL的支持,可以将我们曾经在select clause中使用的correlated subqueries替换为lateral subqueries ,因为这些子查询确实支持引用from clause中引用的其他表的能力。 Additionally (which can't be done in a select clause ) one lateral subquery can refer to the result of any prior lateral subquery which is a really very useful feature, and this is also shown by the example in the documentation:此外(不能在select clause中完成)一个lateral subquery可以引用任何先前lateral subquery的结果,这是一个非常有用的功能,文档中的示例也显示了这一点:

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) -- refers to prior lateral subquery result
  AS max_sale_customer;

So, conventional derived tables cannot use correlations, lateral subqueries can.因此,传统的派生表不能使用相关性,横向子查询可以。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM