Truy vấn lồng nhau trong SQL
Ngôn ngữ SQL cho phép bạn lồng một truy vấn trong một truy vấn khác. Điều này giúp bạn có thể viết một truy vấn rất lớn sẽ thực hiện một số việc lớn và phức tạp, mặc dù khả năng đọc mã giảm đi rất nhiều.
Tùy thuộc vào số lượng giá trị được trả về bởi các truy vấn phụ, khu vực nơi chúng có thể được áp dụng sẽ thay đổi. Tổng cộng có ba lựa chọn:
- Truy vấn con trả về một giá trị duy nhất (một cột và một hàng).
- Truy vấn con trả về một danh sách các giá trị (một bảng có một cột).
- Truy vấn con trả về một bảng (nhiều cột, bất kỳ số hàng nào).
Hãy xem xét một ví dụ cho từng trường hợp.
Truy vấn con với kết quả vô hướng
Hãy tìm danh sách tất cả nhân viên của chúng ta từ bảng nhân viên có mức lương cao hơn mức trung bình của công ty. Làm thế nào chúng ta có thể làm điều đó?
Chúng ta có thể dễ dàng lọc nhân viên bằng cách so sánh mức lương của họ với mức trung bình nếu biết trước. Đồng thời, chúng tôi đã viết một truy vấn cho phép chúng tôi tính mức lương trung bình của nhân viên công ty. Hãy ghi nhớ nó:
SELECT AVG(salary) FROM employee
Sau đó, MySQL trả lại cho chúng tôi giá trị: 76833.3333 .
Làm thế nào bây giờ để tìm danh sách tất cả nhân viên có mức lương trên mức trung bình? Nó cũng rất đơn giản:
SELECT * FROM employee
WHERE salary > 76833.3333
Kết quả của truy vấn này sẽ là:
nhận dạng | tên | nghề nghiệp | lương |
---|---|---|---|
1 | Ivanov Ivan | lập trình viên | 100000 |
2 | Petrov Petr | lập trình viên | 80000 |
4 | Rabinovich Moisha | Giám đốc | 200000 |
Và bây giờ chúng tôi chỉ kết hợp cả hai yêu cầu bằng cách thay thế yêu cầu đầu tiên thay vì giá trị 76833:
SELECT * FROM employee
WHERE salary > (SELECT AVG(salary) FROM employee)
Kết quả của truy vấn này sẽ giống nhau:
nhận dạng | tên | nghề nghiệp | lương |
---|---|---|---|
1 | Ivanov Ivan | lập trình viên | 100000 |
2 | Petrov Petr | lập trình viên | 80000 |
4 | Rabinovich Moisha | Giám đốc | 200000 |
Truy vấn con với danh sách các giá trị
Bạn có nhớ ngày xưa chúng ta có một nhiệm vụ - tìm tất cả các bản ghi từ một bảng mà không có bản ghi tương ứng từ một bảng khác không?
Ngoài ra còn có hình ảnh này:
![](https://cdn.codegym.cc/images/article/a0eff64c-0bb4-4480-833e-c1305cd03a5e/512.jpeg)
Nếu tôi không nhầm thì nhiệm vụ như sau: hiển thị danh sách tất cả nhân viên từ bảng nhân viên mà không có nhiệm vụ nào trong bảng nhiệm vụ .
Hãy cũng tìm ra giải pháp trong hai bước.
Trước tiên, hãy viết một truy vấn sẽ trả về id của tất cả nhân viên có nhiệm vụ trong bảng nhiệm vụ. Chỉ cần nhớ hai điều:
- loại bỏ trùng lặp - sử dụng từ khóa DISTINCT.
- loại bỏ giá trị NULL khỏi kết quả.
SELECT DISTINCT employee_id FROM task
WHERE employee_id IS NOT NULL
Và ở đây chúng tôi đã nhận được một kết quả tuyệt vời của một yêu cầu như vậy:
Mã hiệu công nhân |
---|
1 |
2 |
5 |
4 |
6 |
Ta tạm viết ra cho tiện là dãy số: 1,2,5,4,6. Bây giờ, hãy viết truy vấn thứ hai - vào bảng nhân viên, truy vấn này sẽ trả về danh sách nhân viên có id không có trong danh sách đầu tiên:
SELECT * FROM employee
WHERE id NOT IN (1,2,5,4,6)
Và kết quả của truy vấn này:
nhận dạng | tên | nghề nghiệp | lương | tuổi | ngày tham gia |
---|---|---|---|---|---|
3 | Ivanov Serge | Kiểm thử | 40000 | ba mươi | 2014-01-01 |
Và bây giờ, như trong ví dụ trước, bạn có thể kết hợp cả hai yêu cầu bằng cách thay thế phần thân của yêu cầu đầu tiên thay vì danh sách id.
SELECT * FROM employee
WHERE id NOT IN (
SELECT DISTINCT employee_id FROM task
WHERE employee_id IS NOT NULL
)