Inner Join - внутреннее соединение таблиц
JOIN
в результате остаются только те строки, для которых нашлось соответствие. Выведет строки, если условие соединения выполняется и является истинным TRUE
. Если
не углубляться в то, как внутреннее соединение работает под капотом СУБД, то происходит примерно следующее: каждая
строка из одной таблицы сравнивается с каждой строкой из другой таблицы, строка возвращается, если условие сравнения
является истинным. Общий формальный
синтаксис применения оператора INNER JOIN
:
SELECT `столбцы_таблиц_для_вывода` FROM `основная_таблица`
INNER JOIN вспомогательная_таблица_1 ON условие
INNER JOIN вспомогательная_таблица_2 ON условие; -- возможно применение операторов
После оператора JOIN
идет название второй таблицы, из которой надо добавить данные в выборку. Перед
JOIN
может
использоваться необязательное ключевое слово INNER
. Его наличие или отсутствие ни на что не влияет.
Затем после
ключевого слова ON
указывается условие соединения. Это условие устанавливает, как две таблицы будут
сравниваться. В
большинстве случаев для соединения применяется первичный ключ главной таблицы и внешний ключ зависимой таблицы.
Возьмем таблицу:
CREATE DATABASE IF NOT EXISTS test;
USE test;
CREATE TABLE Products
(
Id INT AUTO_INCREMENT PRIMARY KEY,
ProductName VARCHAR(30) NOT NULL,
Manufacturer VARCHAR(20) NOT NULL,
ProductCount INT DEFAULT 0,
Price DECIMAL NOT NULL
);
CREATE TABLE Customers
(
Id INT AUTO_INCREMENT PRIMARY KEY,
FirstName VARCHAR(30) NOT NULL
);
CREATE TABLE Orders
(
Id INT AUTO_INCREMENT PRIMARY KEY,
ProductId INT NOT NULL,
CustomerId INT NOT NULL,
CreatedAt DATE NOT NULL,
ProductCount INT DEFAULT 1,
Price DECIMAL NOT NULL,
FOREIGN KEY (ProductId) REFERENCES Products(Id) ON DELETE CASCADE,
FOREIGN KEY (CustomerId) REFERENCES Customers(Id) ON DELETE CASCADE
);
Здесь таблицы Products
и Customers
связаны с таблицей Orders
связью один ко
многим. Таблица Orders
в виде внешних ключей ProductId
и CustomerId
содержит
ссылки на столбцы Id
из соответственно таблиц Products
и Customers
. Также она
хранит количество купленного товара (ProductCount
) и и по какой цене он был куплен
(Price
). И кроме того, таблицы также хранит в виде столбца CreatedAt
дату покупки.
Заполним таблицу данными:
USE test;
INSERT INTO Products (ProductName, Manufacturer, ProductCount, Price)
VALUES ('iPhone X', 'Apple', 2, 76000),
('iPhone 8', 'Apple', 2, 51000),
('iPhone 7', 'Apple', 5, 42000),
('Galaxy S9', 'Samsung', 2, 56000),
('Galaxy S8', 'Samsung', 1, 46000),
('Honor 10', 'Huawei', 2, 26000),
('Nokia 8', 'HMD Global', 6, 38000);
INSERT INTO Customers(FirstName) VALUES ('Tom'), ('Bob'),('Sam');
INSERT INTO Orders (ProductId, CustomerId, CreatedAt, ProductCount, Price)
VALUES
(
(SELECT Id FROM Products WHERE ProductName='Galaxy S8'),
(SELECT Id FROM Customers WHERE FirstName='Tom'),
'2018-05-21',
2,
(SELECT Price FROM Products WHERE ProductName='Galaxy S8')
),
(
(SELECT Id FROM Products WHERE ProductName='iPhone X'),
(SELECT Id FROM Customers WHERE FirstName='Tom'),
'2018-05-23',
1,
(SELECT Price FROM Products WHERE ProductName='iPhone X')
),
(
(SELECT Id FROM Products WHERE ProductName='iPhone X'),
(SELECT Id FROM Customers WHERE FirstName='Bob'),
'2018-05-21',
1,
(SELECT Price FROM Products WHERE ProductName='iPhone X')
);
Используя JOIN, выберем все заказы и добавим к ним информацию о товарах:
SELECT Orders.CreatedAt, Orders.ProductCount, Products.ProductName
FROM Orders
JOIN Products ON Products.Id = Orders.ProductId
Поскольку таблицы могут содержать столбцы с одинаковыми названиями, то при указании столбцов для выборки указывается
их
полное имя вместе с именем таблицы, например: название_таблицы.название_столбца
.
Используя псевдонимы для таблиц, можно сократить код:
SELECT O.CreatedAt, O.ProductCount, P.ProductName
FROM Orders AS O
JOIN Products AS P
ON P.Id = O.ProductId
Также можно присоединять данные сразу из нескольких таблиц. Например, добавим к заказу информацию о покупателе из таблицы Customers:
SELECT Orders.CreatedAt, Customers.FirstName, Products.ProductName
FROM Orders
JOIN Products ON Products.Id = Orders.ProductId
JOIN Customers ON Customers.Id=Orders.CustomerId
Благодаря соединению таблиц мы можем использовать их столбцы для фильтрации выборки или ее сортировки:
SELECT Orders.CreatedAt, Customers.FirstName, Products.ProductName
FROM Orders
JOIN Products ON Products.Id = Orders.ProductId
JOIN Customers ON Customers.Id=Orders.CustomerId
WHERE Products.Price > 45000
ORDER BY Customers.FirstName
Условия после ключевого слова ON
могут быть более сложными по составу:
SELECT Orders.CreatedAt, Customers.FirstName, Products.ProductName
FROM Orders
JOIN Products ON Products.Id = Orders.ProductId AND Products.Manufacturer='Apple'
JOIN Customers ON Customers.Id=Orders.CustomerId
ORDER BY Customers.FirstName
В данном случае выбираем все заказы на товары, производителем которых является Apple. При использовании оператора
JOIN
следует учитывать, что процесс соединения таблиц может быть ресурсоемким, поэтому следует
соединять только те таблицы, данные из которых действительно необходимы. Чем больше таблиц соединяется, тем больше
снижается производительность.