Thời gian đọc: 9 phút
LEFT JOIN (hay còn gọi là LEFT OUTER JOIN) là loại liên kết cho phép kết hợp dữ liệu từ hai bảng, trong đó bảng bên trái (bảng đầu tiên được khai báo) sẽ trả về tất cả các hàng, dù có hoặc không có giá trị tương ứng trong bảng bên phải. Nếu không có bản ghi nào tương ứng trong bảng bên phải, các trường của bảng bên phải sẽ được trả về với giá trị NULL.
SELECT column_name(s)
FROM table1
LEFT JOIN table2
ON table1.column_name = table2.column_name;
Giả sử bạn có hai bảng sau:
Bảng Customers
(thông tin khách hàng):
CustomerID | CustomerName | Country |
---|---|---|
1 | John Smith | USA |
2 | Ana Williams | Canada |
3 | Maria Anders | Germany |
Bảng Orders
(thông tin đơn hàng):
OrderID | CustomerID | Product |
---|---|---|
101 | 1 | Laptop |
102 | 2 | Smartphone |
Bây giờ, bạn muốn liệt kê tất cả khách hàng và thông tin về đơn hàng của họ (nếu có). Để làm điều này, bạn sẽ sử dụng LEFT JOIN để lấy tất cả các khách hàng, bao gồm cả những người chưa có đơn hàng.
SELECT Customers.CustomerName, Orders.Product
FROM Customers
LEFT JOIN Orders
ON Customers.CustomerID = Orders.CustomerID;
CustomerName | Product |
---|---|
John Smith | Laptop |
Ana Williams | Smartphone |
Maria Anders | NULL |
Giả sử bạn có thêm một bảng Products và bạn muốn kết hợp thông tin khách hàng, sản phẩm mà họ đã mua và giá của sản phẩm. Nếu một khách hàng chưa có đơn hàng, thông tin của họ vẫn sẽ xuất hiện trong kết quả.
Bảng Products
:
ProductID | ProductName | Price |
---|---|---|
1001 | Laptop | 800 |
1002 | Smartphone | 500 |
Bây giờ bạn muốn liệt kê tất cả các khách hàng và thông tin về sản phẩm mà họ đã mua (nếu có):
SELECT Customers.CustomerName, Products.ProductName, Products.Price
FROM Customers
LEFT JOIN Orders ON Customers.CustomerID = Orders.CustomerID
LEFT JOIN Products ON Orders.ProductID = Products.ProductID;
CustomerName | ProductName | Price |
---|---|---|
John Smith | Laptop | 800 |
Ana Williams | Smartphone | 500 |
Maria Anders | NULL | NULL |
Nếu bạn chỉ muốn liệt kê những khách hàng chưa có đơn hàng, bạn có thể thêm điều kiện vào truy vấn để chỉ lấy các hàng mà Orders.CustomerID là NULL:
SELECT Customers.CustomerName
FROM Customers
LEFT JOIN Orders ON Customers.CustomerID = Orders.CustomerID
WHERE Orders.CustomerID IS NULL;
CustomerName |
---|
Maria Anders |
LEFT JOIN rất phù hợp khi bạn cần truy vấn kết hợp giữa dữ liệu chính và phụ, đặc biệt khi không phải tất cả các bản ghi trong bảng chính đều có dữ liệu tương ứng trong bảng phụ.
Giả sử bạn quản lý một hệ thống bán hàng trực tuyến, và có các bảng sau trong cơ sở dữ liệu:
Bảng Customers
(thông tin khách hàng):
CustomerID | CustomerName | Country |
---|---|---|
1 | John Smith | USA |
2 | Ana Williams | Canada |
3 | Maria Anders | Germany |
4 | Bob Brown | UK |
Bảng Orders
(thông tin đơn hàng):
OrderID | CustomerID | ProductID | OrderDate |
---|---|---|---|
101 | 1 | 1001 | 2024-01-01 |
102 | 2 | 1002 | 2024-01-03 |
103 | 1 | 1003 | 2024-01-05 |
Bảng Products
(thông tin sản phẩm):
ProductID | ProductName | Price |
---|---|---|
1001 | Laptop | 800 |
1002 | Smartphone | 500 |
1003 | Tablet | 300 |
Bạn muốn kết hợp dữ liệu từ các bảng trên để liệt kê tất cả khách hàng, bao gồm cả những người chưa có đơn hàng, và hiển thị các sản phẩm họ đã mua (nếu có).
SELECT Customers.CustomerName, Products.ProductName, Products.Price, Orders.OrderDate
FROM Customers
LEFT JOIN Orders ON Customers.CustomerID = Orders.CustomerID
LEFT JOIN Products ON Orders.ProductID = Products.ProductID;
CustomerName | ProductName | Price | OrderDate |
---|---|---|---|
John Smith | Laptop | 800 | 2024-01-01 |
John Smith | Tablet | 300 | 2024-01-05 |
Ana Williams | Smartphone | 500 | 2024-01-03 |
Maria Anders | NULL | NULL | NULL |
Bob Brown | NULL | NULL | NULL |
Giả sử bạn muốn biết tổng số tiền mà mỗi khách hàng đã chi tiêu, kể cả những khách hàng chưa mua gì (tổng tiền sẽ là NULL đối với những khách hàng đó). Bạn có thể sử dụng hàm SUM() và GROUP BY để tính toán tổng giá trị đơn hàng của mỗi khách hàng:
SELECT Customers.CustomerName, SUM(Products.Price) AS TotalSpent
FROM Customers
LEFT JOIN Orders ON Customers.CustomerID = Orders.CustomerID
LEFT JOIN Products ON Orders.ProductID = Products.ProductID
GROUP BY Customers.CustomerName;
CustomerName | TotalSpent |
---|---|
John Smith | 1100 |
Ana Williams | 500 |
Maria Anders | NULL |
Bob Brown | NULL |
Nếu bạn muốn chỉ lấy danh sách khách hàng chưa có đơn hàng, bạn có thể sử dụng điều kiện lọc với WHERE để kiểm tra xem cột OrderID từ bảng Orders có giá trị NULL hay không:
SELECT Customers.CustomerName
FROM Customers
LEFT JOIN Orders ON Customers.CustomerID = Orders.CustomerID
WHERE Orders.OrderID IS NULL;
CustomerName |
---|
Maria Anders |
Bob Brown |
Để làm cho truy vấn gọn gàng và dễ hiểu hơn, bạn có thể sử dụng bí danh cho các bảng. Đây là cách sử dụng bí danh cho cùng một truy vấn nâng cao với LEFT JOIN:
SELECT C.CustomerName, P.ProductName, P.Price, O.OrderDate
FROM Customers C
LEFT JOIN Orders O ON C.CustomerID = O.CustomerID
LEFT JOIN Products P ON O.ProductID = P.ProductID;
Kết quả tương tự với các ví dụ trước, nhưng việc sử dụng bí danh (C, O, P) giúp câu truy vấn ngắn gọn và dễ đọc hơn.
Nếu bạn muốn lấy danh sách các khách hàng đã chi tiêu trên một mức nào đó, ví dụ như hơn 500, bạn có thể sử dụng HAVING với điều kiện:
SELECT Customers.CustomerName, SUM(Products.Price) AS TotalSpent
FROM Customers
LEFT JOIN Orders ON Customers.CustomerID = Orders.CustomerID
LEFT JOIN Products ON Orders.ProductID = Products.ProductID
GROUP BY Customers.CustomerName
HAVING TotalSpent > 500;
CustomerName | TotalSpent |
---|---|
John Smith | 1100 |
Với các ví dụ trên, bạn có thể thấy LEFT JOIN rất mạnh mẽ trong việc xử lý các bài toán yêu cầu kết hợp dữ liệu từ nhiều bảng, ngay cả khi một số bảng không có thông tin khớp tương ứng.