Database
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Database

Hướng dẫn tham gia SQL

Nối SQL là nơi bạn chạy một truy vấn nối nhiều bảng.

Hướng dẫn nối SQL này trình bày các ví dụ cơ bản về phép nối trong SQL, cũng như giới thiệu về các kiểu nối khác nhau.

Kiểu kết hợp SQL

Tiêu chuẩn ANSI SQL chỉ định năm kiểu kết hợp, như được liệt kê trong bảng sau.

Loại tham gia Mô tả

INNER JOIN
Trả về các hàng khi có ít nhất một hàng trong cả hai bảng phù hợp với điều kiện kết hợp.

LEFT OUTER JOIN
hoặc
LEFT JOIN
Trả về các hàng có dữ liệu trong bảng bên trái (bên trái của JOIN từ khóa), ngay cả khi không có hàng phù hợp trong bảng bên phải.

RIGHT OUTER JOIN
hoặc
RIGHT JOIN
Trả về các hàng có dữ liệu trong bảng bên phải (bên phải của JOIN từ khóa), ngay cả khi không có hàng phù hợp nào trong bảng bên trái.

FULL OUTER JOIN
hoặc
FULL JOIN
Trả về tất cả các hàng, miễn là có dữ liệu khớp trong một trong các bảng.
CROSS JOIN Trả về các hàng kết hợp mỗi hàng từ bảng đầu tiên với mỗi hàng từ bảng thứ hai.

Ngoài ra còn có các điều khoản khác cho các hoạt động kết hợp khác nhau, chẳng hạn như sau:

Tham gia Mô tả
Tự tham gia Khi một bảng kết hợp với chính nó.
Tham gia tự nhiên Một phép nối ngầm dựa trên các cột chung trong hai bảng đang được nối.
Tham gia trang bị Một phép nối chỉ chứa các so sánh bình đẳng trong vị từ phép nối.

Cú pháp kết hợp SQL

Các phép nối bên trong có thể được chỉ định trong FROM hoặc WHERE điều khoản. Các phép nối ngoài và phép nối chéo có thể được chỉ định trong FROM mệnh đề chỉ.

Để tạo một phép nối SQL trong FROM , hãy làm một cái gì đó như thế này:

SELECT *
FROM Table1 < JoinType > Table2 [ ON ( JoinCondition ) ]

Nơi JoinType chỉ định loại kết hợp được thực hiện và JoinCondition xác định vị từ sẽ được đánh giá cho mỗi cặp hàng được kết hợp.

Để chỉ định một tham gia trong WHERE , hãy làm một cái gì đó như thế này:

SELECT *
FROM Table1, Table2 [ WHERE ( JoinCondition ) ]

Một lần nữa, JoinCondition xác định vị từ sẽ được đánh giá cho mỗi cặp hàng được kết hợp.

Ngoài ra, mọi thứ được đặt trong dấu ngoặc vuông ([] ) Là tùy chọn.

Bảng mẫu cho các ví dụ trong Hướng dẫn này

Hầu hết các ví dụ trong hướng dẫn này thực hiện phép nối đối với hai bảng sau.

PetTypes bảng:

+-------------+-----------+
| PetTypeId   | PetType   |
|-------------+-----------|
| 1           | Bird      |
| 2           | Cat       |
| 3           | Dog       |
| 4           | Rabbit    |
+-------------+-----------+
(4 rows affected)

Pets bảng:

+---------+-------------+-----------+-----------+------------+
| PetId   | PetTypeId   | OwnerId   | PetName   | DOB        |
|---------+-------------+-----------+-----------+------------|
| 1       | 2           | 3         | Fluffy    | 2020-11-20 |
| 2       | 3           | 3         | Fetch     | 2019-08-16 |
| 3       | 2           | 2         | Scratch   | 2018-10-01 |
| 4       | 3           | 3         | Wag       | 2020-03-15 |
| 5       | 1           | 1         | Tweet     | 2020-11-28 |
| 6       | 3           | 4         | Fluffy    | 2020-09-17 |
| 7       | 3           | 2         | Bark      | NULL       |
| 8       | 2           | 4         | Meow      | NULL       |
+---------+-------------+-----------+-----------+------------+
(8 rows affected)

Sự tham gia bên trong

INNER JOIN trong SQL trả về các hàng khi có ít nhất một hàng trong cả hai bảng phù hợp với điều kiện kết hợp.

SELECT
    Pets.PetName,
    PetTypes.PetType
FROM Pets
INNER JOIN PetTypes
ON Pets.PetTypeId = PetTypes.PetTypeId;

Kết quả:

-----------+-----------+
| PetName   | PetType   |
|-----------+-----------|
| Fluffy    | Cat       |
| Fetch     | Dog       |
| Scratch   | Cat       |
| Wag       | Dog       |
| Tweet     | Bird      |
| Fluffy    | Dog       |
| Bark      | Dog       |
| Meow      | Cat       |
+-----------+-----------+
(8 rows affected)

Để chỉ định một liên kết bên trong trong FROM , chúng tôi sử dụng INNER JOIN . Chúng tôi cũng sử dụng ON từ khóa để xác định vị từ được đánh giá cho mỗi cặp hàng được nối.

Bất kể loại kết hợp nào, chúng tôi đủ điều kiện cho các tên cột của chúng tôi với các tên bảng. Lý do chúng tôi làm điều này là để tránh bất kỳ sự mơ hồ nào về tên cột giữa các bảng. Cả hai bảng đều có thể có các cột cùng tên (như trong ví dụ của chúng tôi) và trong những trường hợp như vậy, DBMS sẽ không biết bạn đang đề cập đến cột nào. Đặt tiền tố tên cột bằng tên bảng của chúng đảm bảo rằng bạn đang tham chiếu đến cột bên phải và ngăn chặn bất kỳ lỗi nào có thể phát sinh từ bất kỳ sự mơ hồ nào về cột mà bạn đang tham chiếu.

Trong ví dụ này, cả hai bảng đều có PetTypeId cột. Pets.PetTypeId là một khóa ngoại cho PetTypes.PetTypeId , là khóa chính cho bảng đó.

Trong ví dụ này, chúng ta có thể thấy rằng tất cả các vật nuôi đều được trả lại, nhưng không phải tất cả các loại vật nuôi đều được trả lại. Không có thỏ nào trong Pets bảng, và Rabbits loại vật nuôi không được trả lại.

Lý do Rabbits loại không được trả lại là do INNER JOIN chỉ trả về các hàng khi có ít nhất một hàng trong cả hai bảng phù hợp với điều kiện nối. Trong trường hợp này, Rabbits chỉ có trong một bảng (PetTypes bảng).

Lưu ý rằng kiểu tham gia là tùy chọn. Do đó, hầu hết (nếu không phải tất cả) DBMS cho phép bạn bỏ qua INNER từ khóa. Khi bạn bỏ qua điều này (tức là chỉ xác định JOIN ), nó được giả định là một liên kết bên trong.

Do đó, chúng tôi có thể viết lại ví dụ trên thành thế này:

SELECT
    Pets.PetName,
    PetTypes.PetType
FROM Pets
JOIN PetTypes
ON Pets.PetTypeId = PetTypes.PetTypeId;

Ngoài ra, như với bất kỳ câu lệnh SQL nào, FROM mệnh đề có thể ở trên một dòng nếu bạn thích:

SELECT
    Pets.PetName,
    PetTypes.PetType
FROM Pets JOIN PetTypes ON Pets.PetTypeId = PetTypes.PetTypeId;

Bí danh

Thực tế phổ biến là sử dụng bí danh bảng khi thực hiện các phép nối SQL. Bí danh giúp làm cho mã ngắn gọn hơn và dễ đọc hơn.

Do đó, chúng tôi có thể thay đổi ví dụ trước thành sau:

SELECT 
    p.PetName,
    pt.PetType
FROM Pets p INNER JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId;

Kết quả:

-----------+-----------+
| PetName   | PetType   |
|-----------+-----------|
| Fluffy    | Cat       |
| Fetch     | Dog       |
| Scratch   | Cat       |
| Wag       | Dog       |
| Tweet     | Bird      |
| Fluffy    | Dog       |
| Bark      | Dog       |
| Meow      | Cat       |
+-----------+-----------+
(8 rows affected)

Tham gia trang bị

Sự tham gia ở trên cũng có thể được gọi là một tham gia tương đương . Một phép nối tương đương là một phép nối chỉ chứa các so sánh bình đẳng trong vị từ phép nối.

Một cách khác để viết phép nối ở trên là như thế này:

SELECT
    p.PetName,
    pt.PetType
FROM 
    Pets p, 
    PetTypes pt
WHERE p.PetTypeId = pt.PetTypeId;

Kết quả:

+-----------+-----------+
| PetName   | PetType   |
|-----------+-----------|
| Fluffy    | Cat       |
| Fetch     | Dog       |
| Scratch   | Cat       |
| Wag       | Dog       |
| Tweet     | Bird      |
| Fluffy    | Dog       |
| Bark      | Dog       |
| Meow      | Cat       |
+-----------+-----------+

Đây là một ví dụ về việc chỉ định một liên kết bên trong trong WHERE mệnh đề. Chúng tôi chỉ cung cấp danh sách các bảng được phân tách bằng dấu phẩy và sau đó là WHERE điều kiện. Nếu chúng tôi đã bỏ qua WHERE điều kiện, chúng tôi đã kết thúc với một CROSS JOIN .

Nhiều người mới bắt đầu thấy cú pháp trên dễ hiểu hơn nhiều so với INNER JOIN cú pháp. Tuy nhiên, hãy thoải mái sử dụng cú pháp này nếu bạn thích, hãy lưu ý rằng hầu hết các chuyên gia SQL thích sử dụng INNER JOIN cú pháp từ ví dụ trước.

Xem SQL Internal Join để biết thêm ví dụ, bao gồm một phép nối bên trong nối 3 bảng.

Tham gia đúng

Còn được gọi là RIGHT OUTER JOIN , RIGHT JOIN trả về các hàng có dữ liệu trong bảng bên phải (bên phải của JOIN từ khóa), ngay cả khi không có hàng phù hợp nào trong bảng bên trái.

SELECT 
    p.PetName,
    pt.PetType
FROM Pets p
RIGHT JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId;

Kết quả:

+-----------+-----------+
| PetName   | PetType   |
|-----------+-----------|
| Tweet     | Bird      |
| Fluffy    | Cat       |
| Scratch   | Cat       |
| Meow      | Cat       |
| Fetch     | Dog       |
| Wag       | Dog       |
| Fluffy    | Dog       |
| Bark      | Dog       |
| NULL      | Rabbit    |
+-----------+-----------+
(9 rows affected)

Trong trường hợp này, chúng tôi có thêm một PetType giá trị - Rabbit - mặc dù không có vật nuôi nào trong Pets bảng loại đó. Điều này dẫn đến NULL giá trị trong PetName cột chống lại Rabbit .

Xem SQL Right Join để biết thêm ví dụ, bao gồm một phép nối phải nối 3 bảng.

Tham gia bên trái

Còn được gọi là LEFT OUTER JOIN , SQL LEFT JOIN trả về các hàng có dữ liệu trong bảng bên trái (bên trái của JOIN từ khóa), ngay cả khi không có hàng nào phù hợp trong bảng bên phải.

Điều này ngược lại với RIGHT JOIN .

Nếu chúng ta thay đổi ví dụ trước để sử dụng kết nối bên trái, chúng ta sẽ nhận được kết quả sau.

SELECT 
    p.PetName,
    pt.PetType
FROM Pets p
LEFT JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId;

Kết quả:

+-----------+-----------+
| PetName   | PetType   |
|-----------+-----------|
| Fluffy    | Cat       |
| Fetch     | Dog       |
| Scratch   | Cat       |
| Wag       | Dog       |
| Tweet     | Bird      |
| Fluffy    | Dog       |
| Bark      | Dog       |
| Meow      | Cat       |
+-----------+-----------+
(8 rows affected)

Trong trường hợp cụ thể này, kết quả của chúng tôi giống như với phép nối bên trong.

Tuy nhiên, nếu chúng ta hoán đổi thứ tự bảng trong FROM , chúng ta sẽ nhận được một kết quả tương tự với phép nối phải trong ví dụ trước.

SELECT 
    p.PetName,
    pt.PetType
FROM PetTypes pt
LEFT JOIN Pets p
ON p.PetTypeId = pt.PetTypeId;

Kết quả:

+-----------+-----------+
| PetName   | PetType   |
|-----------+-----------|
| Tweet     | Bird      |
| Fluffy    | Cat       |
| Scratch   | Cat       |
| Meow      | Cat       |
| Fetch     | Dog       |
| Wag       | Dog       |
| Fluffy    | Dog       |
| Bark      | Dog       |
| NULL      | Rabbit    |
+-----------+-----------+
(9 rows affected)

Vì vậy, bạn có thể thấy rằng bất kỳ sự khác biệt kết quả nào giữa các phép nối trái và phải chỉ phụ thuộc vào cách bạn sắp xếp các cột trong FROM mệnh đề.

Xem SQL Left Join để biết thêm ví dụ, bao gồm một phép nối bên trái kết hợp 3 bảng.

Tham gia đầy đủ

SQL FULL JOIN (hoặc FULL OUTER JOIN ) trả về tất cả các hàng, miễn là có dữ liệu khớp trong một trong các bảng.

Nói cách khác, nó giống như có cả phép tham gia bên trái và bên phải trong một phép nối.

Dưới đây là một ví dụ về tham gia đầy đủ.

SELECT 
    p.PetName,
    pt.PetType
FROM Pets p
FULL JOIN PetTypes pt
ON p.PetTypeId = pt.PetTypeId;

Kết quả:

+-----------+-----------+
| PetName   | PetType   |
|-----------+-----------|
| Fluffy    | Cat       |
| Fetch     | Dog       |
| Scratch   | Cat       |
| Wag       | Dog       |
| Tweet     | Bird      |
| Fluffy    | Dog       |
| Bark      | Dog       |
| Meow      | Cat       |
| NULL      | Rabbit    |
+-----------+-----------+
(9 rows affected)

Điều này trả về cùng một kết quả mà chúng tôi nhận được với phép nối bên phải, nhưng nó sẽ trả lại một kết quả khác nếu có một hàng trong bảng bên trái không có giá trị tương ứng trong bảng bên phải.

Hãy hoán đổi tên bảng và chạy lại.

SELECT 
    p.PetName,
    pt.PetType
FROM PetTypes pt
FULL JOIN Pets p
ON p.PetTypeId = pt.PetTypeId;

Kết quả:

+-----------+-----------+
| PetName   | PetType   |
|-----------+-----------|
| Tweet     | Bird      |
| Fluffy    | Cat       |
| Scratch   | Cat       |
| Meow      | Cat       |
| Fetch     | Dog       |
| Wag       | Dog       |
| Fluffy    | Dog       |
| Bark      | Dog       |
| NULL      | Rabbit    |
+-----------+-----------+
(9 rows affected)

Kết quả tương tự.

Xem SQL Full Join để biết thêm ví dụ, bao gồm một phép nối đầy đủ nối 3 bảng.

Thập giá tham gia

SQL CROSS JOIN trả về các hàng kết hợp mỗi hàng từ bảng đầu tiên với mỗi hàng từ bảng thứ hai.

Nói cách khác, nó trả về tích số Descartes của các hàng từ các bảng trong phép nối.

SELECT 
    p.PetName,
    pt.PetType
FROM Pets p
CROSS JOIN PetTypes pt;

Kết quả:

+-----------+-----------+
| PetName   | PetType   |
|-----------+-----------|
| Fluffy    | Bird      |
| Fetch     | Bird      |
| Scratch   | Bird      |
| Wag       | Bird      |
| Tweet     | Bird      |
| Fluffy    | Bird      |
| Bark      | Bird      |
| Meow      | Bird      |
| Fluffy    | Cat       |
| Fetch     | Cat       |
| Scratch   | Cat       |
| Wag       | Cat       |
| Tweet     | Cat       |
| Fluffy    | Cat       |
| Bark      | Cat       |
| Meow      | Cat       |
| Fluffy    | Dog       |
| Fetch     | Dog       |
| Scratch   | Dog       |
| Wag       | Dog       |
| Tweet     | Dog       |
| Fluffy    | Dog       |
| Bark      | Dog       |
| Meow      | Dog       |
| Fluffy    | Rabbit    |
| Fetch     | Rabbit    |
| Scratch   | Rabbit    |
| Wag       | Rabbit    |
| Tweet     | Rabbit    |
| Fluffy    | Rabbit    |
| Bark      | Rabbit    |
| Meow      | Rabbit    |
+-----------+-----------+
(32 rows affected)

Như bạn có thể tưởng tượng, điều này có thể rất nguy hiểm nếu bạn chạy nó với các bảng sai.

Nó cũng giống như làm điều này:

SELECT 
    p.PetName,
    pt.PetType
FROM Pets p, PetTypes pt;

Bạn có thể thêm WHERE mệnh đề với một phép nối chéo, điều này sẽ biến nó thành một phép nối bên trong.

Như thế này:

SELECT 
    p.PetName,
    pt.PetType
FROM Pets p
CROSS JOIN PetTypes pt
WHERE p.PetTypeId = pt.PetTypeId;

Kết quả:

+-----------+-----------+
| PetName   | PetType   |
|-----------+-----------|
| Fluffy    | Cat       |
| Fetch     | Dog       |
| Scratch   | Cat       |
| Wag       | Dog       |
| Tweet     | Bird      |
| Fluffy    | Dog       |
| Bark      | Dog       |
| Meow      | Cat       |
+-----------+-----------+
(8 rows affected)

Xem SQL Cross Join để biết thêm ví dụ.

Sự tham gia tự nhiên

SQL NATURAL JOIN là một kiểu nối tương đương trong đó vị từ nối phát sinh ngầm định bằng cách so sánh tất cả các cột trong cả hai bảng có cùng tên cột trong các bảng đã nối.

Tập kết quả chỉ chứa một cột cho mỗi cặp cột được đặt tên bằng nhau. Nếu không tìm thấy cột nào có cùng tên, kết quả sẽ là một phép nối chéo.

SELECT 
    Pets.PetName,
    PetTypes.PetType
FROM Pets NATURAL JOIN PetTypes;

Kết quả:

petname | pettype 
---------+---------
 Fluffy  | Cat
 Fetch   | Dog
 Scratch | Cat
 Wag     | Dog
 Tweet   | Bird
 Fluffy  | Dog
 Bark    | Dog
 Meow    | Cat
(8 rows)

Trên thực tế, phép nối tự nhiên không thực sự là một loại phép nối, theo tiêu chuẩn ANSI. Đây là một từ khóa mà bạn có thể tùy chọn chèn để làm cho việc tham gia trở thành một kết nối tự nhiên.

Do đó, chúng ta có thể thay đổi ví dụ trên thành NATURAL INNER JOIN nếu chúng tôi muốn:

SELECT 
    Pets.PetName,
    PetTypes.PetType
FROM Pets NATURAL INNER JOIN PetTypes;

Như đã đề cập trước đó, liên kết bên trong là loại liên kết mặc định, vì vậy nếu bạn bỏ qua loại liên kết (ví dụ:INNER , LEFT , RIGHT , v.v.), thì nó được coi như một liên kết bên trong.

Nếu định dạng của các kết quả này trông khác với các kết quả trước đó, thì đó là do tôi phải chuyển sang PostgreSQL để chạy truy vấn này. Tôi đã chạy các ví dụ trước đó trong SQL Server, nhưng SQL Server không hỗ trợ kết hợp tự nhiên.

Xem SQL Natural Join để biết thêm ví dụ, bao gồm một phép nối tự nhiên nối 3 bảng.

Tự tham gia

SQL SELF JOIN đang tham gia một bảng với chính nó.

Một ví dụ cổ điển về tự tham gia là trong bảng Nhân viên. Trong một bảng như vậy, một nhân viên có thể báo cáo cho một nhân viên khác. Do đó, bạn có thể sử dụng tự nối để tham gia vào bảng trên cột ID nhân viên và cột ID người quản lý.

Giả sử chúng ta có bảng sau:

+--------------+-------------+------------+-------------+
| EmployeeId   | FirstName   | LastName   | ReportsTo   |
|--------------+-------------+------------+-------------|
| 1            | Homer       | Connery    | NULL        |
| 2            | Bart        | Pitt       | 1           |
| 3            | Maggie      | Griffin    | 1           |
| 4            | Peter       | Farnsworth | 2           |
| 5            | Marge       | Morrison   | NULL        |
| 6            | Lisa        | Batch      | 5           |
| 7            | Dave        | Zuckerberg | 6           |
| 8            | Vlad        | Cook       | 7           |
+--------------+-------------+------------+-------------+

Chúng ta có thể tự tham gia trên bảng này để trả lại tất cả nhân viên và người quản lý của họ.

SELECT
    CONCAT(e1.FirstName, ' ', e1.LastName) AS Employee,
    CONCAT(e2.FirstName, ' ', e2.LastName) AS Manager
FROM Employees e1
LEFT JOIN Employees e2 
ON e1.ReportsTo = e2.EmployeeId;

Kết quả:

+------------------+-----------------+
| Employee         | Manager         |
|------------------+-----------------|
| Homer Connery    |                 |
| Bart Pitt        | Homer Connery   |
| Maggie Griffin   | Homer Connery   |
| Peter Farnsworth | Bart Pitt       |
| Marge Morrison   |                 |
| Lisa Batch       | Marge Morrison  |
| Dave Zuckerberg  | Lisa Batch      |
| Vlad Cook        | Dave Zuckerberg |
+------------------+-----------------+

Xem SQL Self Join để biết thêm ví dụ.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bất ngờ về Hiệu suất và Giả định:DATEADD

  2. Mã hóa dữ liệu minh bạch và luôn được mã hóa

  3. Cải thiện hiệu suất của UDF với NULL ON NULL INPUT

  4. Gói lưu trữ trên Chocolatey

  5. Cách tạo tài liệu Excel từ chương trình Java bằng Apache POI