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.

Cú pháp của LEFT JOIN:

SELECT column_name(s)
FROM table1
LEFT JOIN table2
ON table1.column_name = table2.column_name;

Giải thích:

  • SELECT column_name(s): Chọn các cột bạn muốn lấy dữ liệu.
  • FROM table1: Xác định bảng bên trái.
  • LEFT JOIN table2: Xác định bảng bên phải mà bạn muốn kết hợp với bảng bên trái.
  • ON table1.column_name = table2.column_name: Điều kiện liên kết giữa hai bảng dựa trên cột có giá trị tương ứng.

Ví dụ cơ bản về LEFT JOIN:

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;

Kết quả:

CustomerName Product
John Smith Laptop
Ana Williams Smartphone
Maria Anders NULL

Giải thích:

  • John SmithAna Williams có đơn hàng, nên thông tin đơn hàng của họ được hiển thị.
  • Maria Anders không có đơn hàng, nhưng vì sử dụng LEFT JOIN, tên của cô ấy vẫn xuất hiện trong kết quả, và giá trị của cột Product sẽ là NULL.

So sánh LEFT JOIN và INNER JOIN:

  • INNER JOIN chỉ trả về các hàng có giá trị khớp trong cả hai bảng.
  • LEFT JOIN trả về tất cả các hàng từ bảng bên trái, và các giá trị từ bảng bên phải nếu có bản ghi khớp. Nếu không có, các giá trị từ bảng bên phải sẽ là NULL.

Ví dụ nâng cao với LEFT JOIN:

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;

Kết quả:

CustomerName ProductName Price
John Smith Laptop 800
Ana Williams Smartphone 500
Maria Anders NULL NULL

Giải thích:

  • John SmithAna Williams có đơn hàng, nên sản phẩm và giá của họ được hiển thị.
  • Maria Anders không có đơn hàng, nhưng thông tin của cô ấy vẫn xuất hiện với giá trị NULL ở các cột liên quan đến sản phẩm.

Sử dụng LEFT JOIN với điều kiện:

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.CustomerIDNULL:

SELECT Customers.CustomerName
FROM Customers
LEFT JOIN Orders ON Customers.CustomerID = Orders.CustomerID
WHERE Orders.CustomerID IS NULL;

Kết quả:

CustomerName
Maria Anders

Giải thích:

  • Truy vấn này trả về danh sách các khách hàng chưa có đơn hàng, sử dụng LEFT JOIN và điều kiện WHERE Orders.CustomerID IS NULL để chỉ lấy những khách hàng mà không có giá trị khớp trong bảng Orders.

Khi nào nên sử dụng LEFT JOIN:

  • LEFT JOIN hữu ích khi bạn muốn lấy tất cả các bản ghi từ một bảng, đồng thời kết hợp thông tin từ bảng khác nếu có. Nếu không, các giá trị từ bảng kia sẽ là NULL.
  • Khi bạn cần danh sách đầy đủ từ một bảng (bảng bên trái), bất kể có dữ liệu tương ứng trong bảng bên phải hay không.

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ụ.

Ví dụ nâng cao về LEFT JOIN trong MySQL

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ài toán:

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ó).

Truy vấn nâng cao sử dụng LEFT JOIN trên ba bảng:

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;

Kết quả:

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ải thích:

  • John Smith đã mua 2 sản phẩm (LaptopTablet), và các sản phẩm kèm theo giá và ngày đặt hàng được hiển thị.
  • Ana Williams đã mua Smartphone.
  • Maria AndersBob Brown chưa có đơn hàng, nhưng vẫn xuất hiện trong kết quả với giá trị NULL cho các cột liên quan đến sản phẩm và đơn hàng.

Sử dụng LEFT JOIN với hàm tổng hợp (Aggregate Functions)

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

Kết quả:

CustomerName TotalSpent
John Smith 1100
Ana Williams 500
Maria Anders NULL
Bob Brown NULL

Giải thích:

  • John Smith đã chi tổng cộng 1100 (800 cho Laptop + 300 cho Tablet).
  • Ana Williams đã chi 500 cho Smartphone.
  • Maria AndersBob Brown chưa mua sản phẩm nào, vì vậy tổng tiền của họ là NULL.

Ví dụ nâng cao với điều kiện lọc:

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;

Kết quả:

CustomerName
Maria Anders
Bob Brown

Giải thích:

  • Truy vấn này trả về danh sách các khách hàng chưa có đơn hàng nào (giá trị NULL trong cột OrderID).

Ví dụ với Alias (Bí danh) và LEFT JOIN

Để 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.


Sử dụng LEFT JOIN với điều kiện HAVING

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;

Kết quả:

CustomerName TotalSpent
John Smith 1100

Giải thích:

  • Truy vấn này chỉ trả về những khách hàng có tổng số tiền chi tiêu lớn hơn 500. Trong trường hợp này, chỉ có John Smith thỏa mãn điều kiện.

Khi nào nên sử dụng LEFT JOIN thay vì INNER JOIN?

  • LEFT JOIN phù hợp khi bạn muốn giữ tất cả dữ liệu từ bảng bên trái và chỉ bổ sung dữ liệu từ bảng bên phải nếu có sự khớp. Nó đảm bảo rằng không có dữ liệu từ bảng bên trái bị mất, ngay cả khi không có bản ghi tương ứng trong bảng bên phải.
  • INNER JOIN chỉ nên dùng khi bạn muốn chỉ lấy những bản ghi có sự tương ứng từ cả hai bảng.

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.