MySQL з'єднання таблиць без JOIN


Неявне з'єднання таблиць

Нерідко виникає необхідність в одному запиті отримати дані відразу з декількох таблиць. Для об'єднання даних з різних таблиць ми можемо використовувати різні способи. У цій статті розглянемо не самий поширений, проте досить простий спосіб, який представляє неявне з'єднання таблиць.

Припустимо, у нас є такі таблиці, які пов'язані між собою зв'язками:

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 дату покупки.

Нехай ці таблиці будуть містити такі дані:

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')
);

    
Тепер з'єднаємо дві таблиці Orders і Customers :

SELECT * FROM Orders, Customers;

При такій вибірці кожен рядок з таблиці Orders буде з'єднуватися з кожним рядком з таблиці Customers . Тобто, вийде перехресне з'єднання. Наприклад, в Orders три рядки, а в Customers також три рядки, значить ми отримаємо 3 * 3 = 9 рядків.
Неявне з'єднання таблиць без JOIN в MySQL

Але навряд чи це той результат, який хотілося б бачити. Тим більше кожне замовлення з Orders пов'язане з конкретним покупцем з Customers , а не з усіма можливими покупцями.

Щоб вирішити задачу, необхідно використовувати вираз WHERE і фільтрувати рядки за умови, що поле CustomerId з Orders відповідає полю Id з Customers :

SELECT * FROM Orders, Customers
WHERE Orders.CustomerId = Customers.Id;

З'єднання таблиць без JOIN в MySQL

Тепер об'єднаємо дані по трьох таблицях Orders , Customers і Proucts . Тобто отримаємо всі замовлення і додамо інформацію по клієнту і пов'язаного товару:

SELECT Customers.FirstName, Products.ProductName, Orders.CreatedAt
FROM Orders, Customers, Products
WHERE Orders.CustomerId = Customers.Id AND Orders.ProductId=Products.Id;

Так як тут потрібно з'єднати три таблиці, то застосовуються як мінімум дві умови. Ключовий таблицею залишається Orders, з якої витягуються всі замовлення, а потім до неї приєднується дані по клієнту за умовою Orders.CustomerId = Customers.Id і дані по товару за умовою Orders.ProductId=Products.Id

В даному випадку назви таблиць сильно збільшують код, але ми його можемо скоротити за рахунок використання псевдонімів таблиць:

SELECT C.FirstName, P.ProductName, O.CreatedAt
FROM Orders AS O, Customers AS C, Products AS P
WHERE O.CustomerId = C.Id AND O.ProductId=P.Id;

Якщо необхідно при використанні псевдоніма вибрати всі стовпці з певної таблиці, то можна використовувати зірочку:

SELECT C.FirstName, P.ProductName, O.*
FROM Orders AS O, Customers AS C, Products AS P
WHERE O.CustomerId = C.Id AND O.ProductId=P.Id;

Наш партнер:
beta test mp3 playlist downloader