Hỏi Đáp

Join (SQL) – Wikipedia tiếng Việt

Một từ khóa join kết nối nhiều bản ghi từ 2 bảng dữ liệu trong 1 cơ sở dữ liệu quan hệ và kết quả được đưa vào một bảng (tạm). Trong ngôn ngữ truy vấn theo cấu trúc (SQL) có ba loại kết hợp sau: nội, ngoại và chéo. Kết ngoại được chia ra thêm thành kết ngoại bên trái (left outer join), kết ngoại bên phải (right outer join), và kết ngoại đủ (full outer join).

Về mặt toán học, phép tích hợp là 1 cấu trúc quan hệ, 1 thao tác cơ bản trong đại số quan hệ và tổng quát hóa và là khái quát hóa của cấu trúc hàm .

Ví dụ trên bảng[sửa|sửa mã nguồn]

Những ví dụ dưới đây về phép phối hợp sử dụng hai bảng sau :

Bảng “employee”
LastName DepartmentID
Smith 34
Jones 33
Robinson 34
Jasper 36
Steinberg 33
Rafferty 31
Bảng “department”
DepartmentName DepartmentID
Sales 31
Engineering 33
Clerical 34
Marketing 35

Để minh họa, ta cần chú ý rằng DepartmentID của nhân viên Jasper không có dòng tương ứng nào trong bảng department, và phòng Marketing thì không có dòng tương ứng trong bảng employee.

Các hình thức tích hợp[sửa|sửa mã nguồn]

Một phép kết nội (inner join) thực chất là tìm giao của hai bảng dữ liệu. Đây là loại kết hợp thường được dùng nhất và được xem như là phép kết hợp mặc định. Ví dụ dưới đây về phép kết hợp trích tất cả các bản ghi trong bảng dữ liệu A (employee) và tìm những bản ghi tương ứng trong bảng B (department). Nếu không tìm được, những bản ghi trong A sẽ không được đưa vào kết quả. Nếu có nhiều kết quả tìm được trong B tương ứng với vị từ, thì 1 dòng sẽ được trả về ứng với mỗi vị từ (giá trị ở bảng A sẽ được lặp).

Cần đặc biệt quan trọng chú ý quan tâm khi phối hợp những bảng trên những cột mà hoàn toàn có thể là NULL vì giá trị NULL sẽ không khi nào có tương ứng. Xem giải pháp ở Phép Kết Ngoại Trái và Phép Kết Ngoại phảiVí dụ về phép kết nội ( cú pháp chuẩn ANSI 92 ) :

SELECT * 
FROM employee 
INNER JOIN department 
ON employee.DepartmentID = department.DepartmentID

Ví dụ về phép kết nội ( cú pháp không chuẩn ) :

SELECT * 
FROM employee, department 
WHERE employee.DepartmentID = department.DepartmentID

Kết quả phối hợp :

+-----------+--------------+----------------+--------------+
| LastName | DepartmentID | DepartmentName | DepartmentID |
+-----------+--------------+----------------+--------------+
| Smith |  34 | Clerical  |  34 |
| Jones |  33 | Engineering  |  33 |
| Robinson |  34 | Clerical  |  34 |
| Steinberg |  33 | Engineering  |  33 |
| Rafferty |  31 | Sales   |  31 |
+-----------+--------------+----------------+--------------+

Chú ý rằng nhân viên cấp dưới Jasper và phòng Marketing không Open. Không một bản nào trong những bản này có dòng tương ứng trong bảng phối hợp của chúng, nên đã bị loại ra khỏi hiệu quả của phép kết nội này .

Kết ngoại bên trái[sửa|sửa mã nguồn]

Một phép kết ngoại bên trái (left outer join) khác rất nhiều với 1 phép kết nội. Thay vì giới hạn những kết quả thu được trong cả hai bảng, nó chỉ giới hạn đối với những kết quả ở bảng bên trái (A). Nghĩa là nếu mệnh đề ON không có bản ghi tương ứng bên bảng B, 1 dòng trong kết quả vẫn được trả về nhưng với giá trị NULL cho mỗi cột trong bảng B.

Nó trả về tất cả những giá trị từ bản bên trái + những giá trị tương ứng với bảng bên phải hoặc là null (khi những giá trị ở bảng bên phải không tương ứng)

Chẳng hạn, nó được cho phép ta tìm phòng ban của nhân viên cấp dưới, nhưng vẫn trả về nhân viên cấp dưới ngay cả khi phòng ban của người ấy là NULL hoặc không sống sót. Ví dụ ở trên sẽ bỏ lỡ những nhân viên cấp dưới trong phòng ban không sống sót .Ví dụ về phép kết ngoại bên trái ( cú pháp chuẩn ANSI 92 ) :

SELECT distinct * 
FROM employee 
LEFT OUTER JOIN 
department 
 ON employee.DepartmentID = department.DepartmentID

Ví dụ về phép kết ngoại bên trái ( cú pháp không chuẩn ) :

SELECT *
FROM employee, department
WHERE employee.DepartmentID = department.DepartmentID(+)
+-----------+--------------+----------------+--------------+
| LastName | DepartmentID | DepartmentName | DepartmentID |
+-----------+--------------+----------------+--------------+
| Smith |  34 | Clerical  |  34 |
| Jones |  33 | Engineering  |  33 |
| Robinson |  34 | Clerical  |  34 |
| Jasper  |  36 | NULL  |   NULL |
| Steinberg |  33 | Engineering  |  33 |
| Rafferty |  31 | Sales   |  31 |
+-----------+--------------+----------------+--------------+

Trong cú pháp không chuẩn, dấu (+) ngụ ý rằng bảng department phải được mở rộng (bằng giá trị NULL) cho những dòng không tương ứng tồn tại trong bảng employee.
Dấu (+) chỉ được dùng trong một số hệ quản trị CSDL, một số hệ quản trị CSDL không hiểu dấu (+). Sau đây là mã lỗi (Server: Msg 170, Level 15, State 1, Line 3
Line 3: Incorrect syntax near ‘)’)

Kết ngoại bên phải[sửa|sửa mã nguồn]

Một phép kết ngoại bên phải (right outer join) hầu như tương tự với phép kết ngoại bên trái, trừ 1 điều là thứ tự các bảng đổi lại. Mỗi bản ghi từ bảng bên phải, B hoặc department sẽ được trả về và giá trị NULL sẽ được trả về cho những dòng mà không có bản ghi tương ứng bên bảng A.

Nó trả về tất cả những giá trị từ bảng bên phải + giá trị tương ứng từ bảng bên trái (hoặc null)

Ví dụ về phép kết ngoại bên phải ( cú pháp chuẩn ANSI 92 ) :

SELECT * 
FROM employee 
RIGHT OUTER JOIN 
department 
 ON employee.DepartmentID = department.DepartmentID

Ví dụ về phép kết ngoại bên phải ( cú pháp không chuẩn ) :

SELECT *
FROM employee, department
WHERE employee.DepartmentID(+) = department.DepartmentID
+-----------+--------------+----------------+--------------+
| LastName | DepartmentID | DepartmentName | DepartmentID |
+-----------+--------------+----------------+--------------+
| Smith |  34 | Clerical  |  34 |
| Jones |  33 | Engineering  |  33 |
| Robinson |  34 | Clerical  |  34 |
| Steinberg |  33 | Engineering  |  33 |
| Rafferty |  31 | Sales   |  31 |
| NULL |   NULL | Marketing |  35 |
+-----------+--------------+----------------+--------------+

Kết ngoại đủ[sửa|sửa mã nguồn]

Một phép kết ngoại đủ (full outer join) kết hợp cả kết quả của cả phép kết ngoại bên trái và phép kết ngoại bên phải. Những phép kết này đưa ra bản ghi của cả hai bảng dữ liệu, và lấp đầy những dòng tương ứng bị thiếu của cả hai phía bằng NULLs.

Một vài hệ cơ sở tài liệu không tương hỗ tính năng này, nhưng nó hoàn toàn có thể được sửa chữa thay thế bằng việc dùng phép kết ngoại bên trái và bên phải và phép hợp ( union ). ( Xem dưới đây )Ví dụ về phép kết ngoại đủ ( cú pháp chuẩn ANSI 92 ) :

SELECT * 
FROM employee 
FULL OUTER JOIN 
department 
 ON employee.DepartmentID = department.DepartmentID
+-----------+--------------+----------------+--------------+
| LastName | DepartmentID | DepartmentName | DepartmentID |
+-----------+--------------+----------------+--------------+
| Smith |  34 | Clerical  |  34 |
| Jones |  33 | Engineering  |  33 |
| Robinson |  34 | Clerical  |  34 |
| Jasper  |  36 | NULL  |   NULL |
| Steinberg |  33 | Engineering  |  33 |
| Rafferty |  31 | Sales   |  31 |
| NULL |   NULL | Marketing |  35 |
+-----------+--------------+----------------+--------------+

Cùng 1 ví dụ, cho những cơ sở tài liệu không tương hỗ phép kết ngoại đủ :

SELECT
employee.LastName,
employee.DepartmentID, 
department.DepartmentName,
department.DepartmentID
FROM employee 
LEFT JOIN 
department 
 ON employee.DepartmentID = department.DepartmentID
UNION
SELECT
employee.LastName,
employee.DepartmentID, 
department.DepartmentName,
department.DepartmentID
FROM employee
RIGHT JOIN
department
 ON employee.DepartmentID = department.DepartmentID
 WHERE employee.DepartmentID IS NULL

Mặc dù không được sử dụng thường xuyên, một phép kết chéo (cross join) là cơ sở mà dựa trên đó phép kết nội được tạo nên. Một phép kết chéo trả về tích Descartes của những tập hợp các dòng từ những bảng được kết.

Câu SQL dùng cho phép kết chéo liệt kê những bảng dữ liệu sẽ được kết (FROM), nhưng không bao gồm bất cứ vị từ lọc nào (WHERE).

Ví dụ về phép kết chéo ( cú pháp chuẩn ANSI 92 ) :

SELECT *
FROM employee CROSS JOIN 
department;

Ví dụ về phép kết chéo (cú pháp thay thế):

SELECT *
FROM employee, department;
+-----------+---------------+----------------+--------------+
| LastName | DepartmentID | DepartmentName | DepartmentID |
+-----------+---------------+----------------+--------------+
| Smith |  34 | Sales   |  31 |
| Smith |  34 | Engineering  |  33 |
| Smith |  34 | Clerical  |  34 |
| Smith |  34 | Marketing |  35 |
| Jones |  33 | Sales   |  31 |
| Jones |  33 | Engineering  |  33 |
| Jones |  33 | Clerical  |  34 |
| Jones |  33 | Marketing |  35 |
| Robinson |  34 | Sales   |  31 |
| Robinson |  34 | Engineering  |  33 |
| Robinson |  34 | Clerical  |  34 |
| Robinson |  34 | Marketing |  35 |
| Jasper  |  36 | Sales   |  31 |
| Jasper  |  36 | Engineering  |  33 |
| Jasper  |  36 | Clerical  |  34 |
| Jasper  |  36 | Marketing |  35 |
| Steinberg |  33 | Sales   |  31 |
| Steinberg |  33 | Engineering  |  33 |
| Steinberg |  33 | Clerical  |  34 |
| Steinberg |  33 | Marketing |  35 |
| Rafferty |  31 | Sales   |  31 |
| Rafferty |  31 | Engineering  |  33 |
| Rafferty |  31 | Clerical  |  34 |
| Rafferty |  31 | Marketing |  35 |
+-----------+---------------+----------------+--------------+

Ta hoàn toàn có thể thấy phép kết chéo không tìm những bản ghi tương ứng. Phép kết này ít khi được dùng, ngoại trừ để phát sinh tổng thể những phối hợp có năng lực của những bản ghi từ những bảng tài liệu mà không san sẻ thành phần chung .Nếu A và B là 2 tập hợp thì phép kết chéo tạo ra | A | x | B | bản ghi ở tác dụng ( với | X | là lực lượng ( số thành phần ) của tập hợp X )