INNER JOIN и LEFT JOIN
Главная операция реляционных баз — соединение таблиц по ключу.
JOIN соединяет строки двух таблиц по условию связи, собирая данные из обеих в одну строку результата.
INNER JOIN — только совпадения
Вернёмся к клиентам и заказам. Чтобы показать имя клиента рядом с суммой заказа, соединяем таблицы по customer_id. INNER JOIN (можно писать просто JOIN) оставляет только те строки, для которых нашлась пара в обеих таблицах.
CREATE TABLE customers (id INTEGER PRIMARY KEY, name TEXT);
CREATE TABLE orders (id INTEGER PRIMARY KEY, customer_id INTEGER, amount INTEGER);
INSERT INTO customers (id, name) VALUES (1, 'Аня'), (2, 'Борис'), (3, 'Вера');
INSERT INTO orders (customer_id, amount) VALUES (1, 500), (1, 1200), (2, 800);
SELECT c.name, o.amount
FROM orders o
JOIN customers c ON c.id = o.customer_id
ORDER BY o.amount;
Вывод:
Аня|500 Борис|800 Аня|1200
Обратите внимание на псевдонимы таблиц: orders o и customers c. Они делают запрос короче (o.amount вместо orders.amount) и обязательны, когда в таблицах есть одноимённые столбцы. Веры в результате нет — у неё нет заказов, а INNER JOIN отбрасывает строки без пары.
LEFT JOIN — сохранить всех слева
А что если нужно показать всех клиентов, даже без заказов? Тут поможет LEFT JOIN: он берёт все строки левой таблицы, а если пары справа нет — подставляет NULL.
CREATE TABLE customers (id INTEGER PRIMARY KEY, name TEXT);
CREATE TABLE orders (id INTEGER PRIMARY KEY, customer_id INTEGER, amount INTEGER);
INSERT INTO customers (id, name) VALUES (1, 'Аня'), (2, 'Борис'), (3, 'Вера');
INSERT INTO orders (customer_id, amount) VALUES (1, 500), (2, 800);
SELECT c.name, o.amount
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
ORDER BY c.name;
Вывод:
Аня|500 Борис|800 Вера|
Вера осталась в результате, но её amount пустой (NULL) — у неё нет заказов. LEFT JOIN незаменим, когда важно не потерять строки без пары: «все клиенты и их заказы (если есть)».
Соединение трёх таблиц
JOIN-ы можно складывать в цепочку. Добавим к заказам позиции (items) и соберём, кто что заказал:
CREATE TABLE customers (id INTEGER PRIMARY KEY, name TEXT);
CREATE TABLE orders (id INTEGER PRIMARY KEY, customer_id INTEGER);
CREATE TABLE items (id INTEGER PRIMARY KEY, order_id INTEGER, product TEXT);
INSERT INTO customers (id, name) VALUES (1, 'Аня'), (2, 'Борис');
INSERT INTO orders (id, customer_id) VALUES (10, 1), (11, 2);
INSERT INTO items (order_id, product) VALUES
(10, 'Книга'), (10, 'Ручка'), (11, 'Тетрадь');
SELECT c.name, i.product
FROM customers c
JOIN orders o ON o.customer_id = c.id
JOIN items i ON i.order_id = o.id
ORDER BY c.name, i.product;
Вывод:
Аня|Книга Аня|Ручка Борис|Тетрадь
Итог
INNER JOIN(он жеJOIN) оставляет только строки, у которых есть пара в обеих таблицах.LEFT JOINсохраняет все строки левой таблицы, подставляя NULL вместо отсутствующей пары.- Псевдонимы таблиц (
orders o) сокращают запрос; JOIN-ы можно объединять в цепочку.