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:

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 
   )