
FROM절에서 서브쿼리를 통해 생성되는 임시 테이블을 Derived Table이라고 합니다. 그리고 Lateral Derived Table은 조금 특별한 형태의 Derived Table을 말합니다.
LATERAL은 MySQL 8.0.14버전에 새롭게 추가된 키워드인데요. 일반적인 Derived Table은 동일한 FROM절에 있는 선행 테이블의 컬럼값을 참조할 수 없지만 LATERAL키워드를 선언한 Lateral Derived Table은 동일한 FROM절에 있는 선행 테이블의 컬럼값을 참조할 수 있습니다.

간단한 예시로 Lateral에 대해 살펴보겠습니다.
CREATE TABLE balance(
id int NOT NULL AUTO_INCREMENT,
name varchar(50) NOT NULL,
balance int NOT NULL,
PRIMARY KEY (id)
);
SELECT
t1.id,
t1.balance,
t2.multiple_balance
FROM
balance t1,
(SELECT t1.balance * 10 AS multiple_balance FROM DUAL) t2
;
(SELECT t1.balance * 10 AS multiple_balance FROM DUAL) t2라는 Derived Table이 정의되어 있습니다.쿼리를 실행하면 아래와 같이 실패합니다.

이번에는 Derived Table에 LATERAL키워드를 사용해 실행해 보겠습니다.
SELECT
t1.id,
t1.balance,
t2.multiple_balance
FROM
balance t1,
LATERAL (SELECT t1.balance * 10 AS multiple_balance FROM DUAL) t2
;
이번에는 쿼리가 정상적으로 잘 실행됩니다.

LATERAL키워드로 인해 서브쿼리에서 선행 테이블(t1)의 컬럼값(balance)에 접근이 가능해졌습니다.
LATERAL은 Join과 함께 사용할 때도 유용합니다.
SELECT
FROM A JOIN (SELECT FROM t1 WHERE t1.id = A.id) as B
ON A.col = B.col
이때 LATERAL키워드를 이용하면 선행 테이블의 컬럼값을 참조할 수 있습니다.
SELECT
FROM A JOIN LATERAL (SELECT FROM t1 WHERE t1.id = A.id) as B
ON
ㅤ
이번에도 구체적인 예시로 살펴보겠습니다.
CREATE TABLE categories (
id int NOT NULL AUTO_INCREMENT,
name varchar(50) NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE articles (
id int NOT NULL AUTO_INCREMENT,
category_id int NOT NULL,
title varchar(255) NOT NULL,
views int NOT NULL,
PRIMARY KEY (id),
KEY ix_categoryid_views (category_id, views)
);
category별로 article이 몇개 있는지 확인하려면 어떻게 해야 할까요?
SELECT categories.name, count(*)
FROM categories
LEFT JOIN articles
ON categories.id = articles.category_id
GROUP BY categories.id;
SELECT c.name, t.count
FROM categories c
LEFT JOIN LATERAL (
SELECT count(*) AS count
FROM articles a
WHERE a.category_id = c.id
) as t
ON TRUE;
WHERE a.category_id = c.id를 실행할 수 없습니다.Join의 ON절에 있어야 할 조건이 서브쿼리의 WHERE절에서 사용되는 경우가 많습니다. ON TRUE와 같은 방식으로 표현해줘야 합니다. Lateral Derived Table을 이용하면 '카테고리 별로 views수가 높은 데이터를 3개씩 추출하라'와 같은 요구사항을 쉽게 만족시킬 수 있습니다.
SELECT c.name, a.title, a.views
FROM categories c
INNER JOIN LATERAL (
SELECT category_id, title, views
FROM articles
WHERE category_id = c.id
ORDER BY category_id DESC, views DESC
LIMIT 3
) a