mysql 8.0.14+才支持lateral,低版本报语法错误;仅限from子句使用,不可用于where或select;正确写法为from t1 join lateral (子查询) as t2 on true或逗号隐式join。

MySQL 8.0.14+ 才真正支持 LATERAL,低版本或写错位置会直接报语法错误,不是慢,是根本跑不起来。
必须确认 MySQL 版本和语法位置
LATERAL 只能在 FROM 子句中使用,不能出现在 WHERE、SELECT 或子查询的 IN 里。常见失败写法:SELECT *, (LATERAL SELECT ...) 或 WHERE EXISTS LATERAL (...) —— 这两种都会触发解析失败。
- 正确结构只有两种:
FROM t1 JOIN LATERAL (SELECT ... WHERE t2.x = t1.y) AS t2 ON TRUE,或逗号隐式写法:FROM t1, LATERAL (SELECT ...) AS t2 - 版本低于 8.0.14(比如 8.0.13)会报
Unknown syntax,不是警告,是硬性拒绝执行 -
ON TRUE是必需占位符:因为LATERAL的关联逻辑已移入子查询内部,外部ON不能再写条件,否则会被忽略或报错
LATERAL 在 UPDATE/DELETE 中不可直接用
LATERAL 是 FROM 子句特性,而标准 UPDATE 和 DELETE 语句不支持 FROM + LATERAL 组合。想在 DML 中复用横向逻辑,得靠中间层:
- 先用
SELECT ... LATERAL构造结果集,再用它驱动UPDATE—— 比如UPDATE t1 JOIN (SELECT ... FROM t1 JOIN LATERAL (...) AS t2) AS tmp ON t1.id = tmp.id SET ... - CTE 更适合 DML 场景:
WITH ranked AS (SELECT ..., ROW_NUMBER() OVER (PARTITION BY dept_id ORDER BY salary DESC) rn FROM employees) UPDATE emp SET status = 'TOP3' WHERE id IN (SELECT id FROM ranked WHERE rn - 别指望
LATERAL直接嵌进UPDATE ... SET x = (LATERAL SELECT ...)—— 语法不合法,MySQL 不认
子查询字段必须有高效索引支撑
用了 LATERAL 不等于自动变快。如果子查询里有 ORDER BY ... LIMIT 1,但没建对联合索引,照样全表扫描。
- 例如查每个订单最新物流状态:
LATERAL (SELECT status FROM logistics WHERE order_id = o.id ORDER BY update_time DESC LIMIT 1),必须建INDEX idx_order_time (order_id, update_time DESC) - MySQL 5.7 不支持降序索引,
DESC会被忽略,排序仍走Using filesort;只有 8.0+ 才真正生效 - 没索引时,
LATERAL反而比普通JOIN更慢 —— 因为它是逐行触发,外层 10 万行,子查询就执行 10 万次
真正容易被忽略的是:LATERAL 解决的是“语法表达力”问题,不是“性能银弹”。它让过去只能靠变量、临时表或应用层循环实现的逻辑,能写进一条 SQL;但每行触发一次的本质没变,索引设计、统计信息、执行计划是否物化临时表,这些底层细节一个都不能松。











