繁体   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?

派生表不能包含对同一 SELECT 的其他表的引用”是什么意思? 我在 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;

派生表不能包含对同一 SELECT 的其他表的引用(为此使用 LATERAL 派生表;请参阅第 13.2.11.9 节,“横向派生表”)

理解这一点的关键在于您已阅读的手册:

派生表在查询期间必须保持不变,不包含对其他 FROM 子句表的列的引用。

也就是说,将派生表视为在查询的初始时间运行,在连接表中的任何行被读取之前。 如果派生表子查询包括对连接表的任何引用,则派生表的结果将取决于从这些表中读取的数据。 可能与派生表为常量的要求相冲突。

LATERAL改变了这一点。 它确保在查询开始从联接表中读取行之后,稍后评估派生表。

PS:上面 jarlh 的评论并不完全正确。 出于其他原因,建议使用显式JOIN语法(例如,它支持外连接等),但对于LATERAL而言,它不是必需的。

文档( 此处)试图解释,如果您从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;

在上面的查询中,您可以看到 from 表是salesperson ,但在correlated subquery中,您也可以引用salesperson correlation是子查询通过结果集逐行执行,该子查询的每次迭代都使用salesperson.id作为 where 子句的输入。 (顺便说一下,这种“逐行”效应通常是为什么correlated subqueries会导致查询速度变慢。)

但是,在from clause中的传统derived tables中,不允许使用上述correlation 因此,下面的示例将失败,因为它尝试使用不允许的与销售人员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;

正如文档所述,这将导致错误:

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

但是,通过增加对LATERAL的支持,可以将我们曾经在select clause中使用的correlated subqueries替换为lateral subqueries ,因为这些子查询确实支持引用from clause中引用的其他表的能力。 此外(不能在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;

因此,传统的派生表不能使用相关性,横向子查询可以。

暂无
暂无

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

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