MySQL 的 LATERAL 派生表

dalang · · 100 次点击 · · 开始浏览    
--- ### **一、MySQL 的 LATERAL 派生表(横向关联)** 1. **功能支持** • **版本要求**:从 **MySQL 8.0.14** 开始支持 `LATERAL` 关键字。 • **核心作用**:在 `FROM` 子句中的派生表(子查询)中,允许直接引用外层表的字段,实现类似“逐行关联”的效果。例如: ```sql SELECT t1.id, t2.* FROM t1, LATERAL (SELECT * FROM t2 WHERE t2.col = t1.col) AS t2; ``` 此查询会为 `t1` 的每一行执行一次子查询 `t2`,并将结果关联。 2. **与 Hive LATERAL VIEW 的区别** • **应用场景差异**: ◦ **Hive**:主要用于展开复杂数据类型(如数组、Map),配合 `EXPLODE` 函数生成多行结果。 ◦ **MySQL**:侧重通过横向关联优化多表查询逻辑,例如逐行计算或动态筛选。 • **语法形式**: ◦ Hive 的 `LATERAL VIEW EXPLODE()` 是专门用于数组展开的语法,而 MySQL 的 `LATERAL` 是通用横向关联机制。 --- ### **二、典型使用场景** 1. **动态关联子查询** 当需要根据外层表字段动态生成子查询结果时,例如为每个用户生成最近 3 条订单记录: ```sql SELECT u.user_id, o.order_date FROM users u LATERAL ( SELECT order_date FROM orders WHERE user_id = u.user_id ORDER BY order_date DESC LIMIT 3 ) AS o; ``` 2. **替代复杂的 JOIN 操作** 在需要逐行处理逻辑的场景中(如计算行级统计值),`LATERAL` 可简化多层嵌套查询。例如统计每个部门的最高工资员工: ```sql SELECT d.dept_name, e.emp_name, e.salary FROM departments d LATERAL ( SELECT emp_name, salary FROM employees WHERE dept_id = d.dept_id ORDER BY salary DESC LIMIT 1 ) AS e; ``` --- ### **三、限制与注意事项** 1. **语法限制** • **位置约束**:`LATERAL` 派生表只能出现在 `FROM` 子句中,且需符合特定的 JOIN 类型(如 `INNER JOIN`、`LEFT JOIN`)。 • **聚合函数限制**:若子查询中包含聚合函数(如 `SUM()`),则外层查询不能是聚合操作的目标。 2. **性能影响** • **潜在风险**:若外层表数据量较大,逐行执行子查询可能导致性能下降。需通过执行计划(`EXPLAIN`)分析是否生成临时表(如 `MATERIALIZED` 标记)。 • **优化建议**:合理使用索引(如子查询中关联字段的索引)以减少重复计算。 --- ### **四、替代方案** 若需处理类似 Hive 中数组展开的场景(如 JSON 数组解析),可使用 MySQL 的 **JSON_TABLE() 函数**: ```sql SELECT t.id, j.item FROM my_table t, JSON_TABLE(t.items, '$[*]' COLUMNS (item VARCHAR(20) PATH '$')) AS j; ``` 此函数将 JSON 数组展开为多行,实现类似 `LATERAL VIEW EXPLODE` 的效果。 --- ### **总结** • **支持性**:MySQL 通过 `LATERAL` 关键字支持横向关联,但语法和场景与 Hive 的 `LATERAL VIEW` 不同。 • **适用性**:适合需要逐行动态关联子查询的场景,而非直接展开复杂数据类型。 • **建议**:在涉及动态行级关联时优先使用 `LATERAL`,处理 JSON/数组展开时结合 `JSON_TABLE()`。
100 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传