MySQL Java JavaScript PHP Python HTML-CSS C-sharp C++ Go

Unirea implicită a tabelelor

Adesea apare nevoia de a obține date într-o singură interogare din mai multe tabele. Pentru consolidarea datelor din tabele diferite, se pot utiliza diferite metode. În acest articol, vom examina o metodă nu foarte răspândită, dar destul de simplă, care implică unirea implicită a tabelelor.

Să presupunem că avem următoarele tabele, care sunt legate între ele prin relații:

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

Aici, tabelele Products și Customers sunt legate de tabela Orders printr-o relație de tipul unu-la-multe. Tabela Orders, sub formă de chei străine ProductId și CustomerId, conține referințe către coloanele Id din tabelele Products și Customers, respectiv.

De asemenea, aceasta stochează cantitatea de produs achiziționată (ProductCount) și prețul la care a fost achiziționat (Price). În plus, tabela stochează și data achiziției sub forma coloanei CreatedAt.

Hai să presupunem că aceste tabele conțin următoarele date:

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

Acum să unim cele două tabele Orders și Customers:

SELECT * FROM Orders, Customers;

Într-o astfel de selecție, fiecare rând din tabela Orders se va uni cu fiecare rând din tabela Customers. Cu alte cuvinte, se obține o uniune transversală. De exemplu, în Orders sunt trei rânduri, iar în Customers, de asemenea, sunt trei rânduri, deci vom obține 3 * 3 = 9 rânduri:

Dar este puțin probabil că acesta este rezultatul dorit. Mai ales că fiecare comandă din Orders este legată de un client specific din Customers, nu de toți clienții posibili.

Pentru a rezolva această problemă, este necesar să utilizăm expresia WHERE și să filtrăm rândurile în condiția în care câmpul CustomerId din Orders corespunde câmpului Id din Customers:

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

Acum vom uni datele din cele trei tabele Orders, Customers și Products. Cu alte cuvinte, vom obține toate comenzile și vom adăuga informații despre client și produsul asociat:

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

Deoarece aici trebuie să unim trei tabele, cel puțin două condiții sunt aplicate. Tabelul cheie rămâne Orders, din care se extrag toate comenzile, și apoi sunt atașate datele despre client în funcție de condiția Orders.CustomerId = Customers.Id și datele despre produs în funcție de condiția Orders.ProductId=Products.Id:

În acest caz, numele tabelelor măresc considerabil codul, dar putem să-l reducem folosind pseudonime de tabel:

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;

Dacă este necesar să selectăm toate coloanele dintr-o anumită tabelă atunci când folosim un pseudonim, putem utiliza asteriscul (*):

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;