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

Cách viết các truy vấn phức tạp trong SQL

Các truy vấn điển hình trong định dạng bảng SELECT * FROM đôi khi là không đủ. Khi dữ liệu cho một truy vấn không nằm trong một bảng mà ở nhiều bảng hoặc khi cần chỉ định nhiều tham số lựa chọn cùng một lúc, bạn sẽ cần các truy vấn phức tạp hơn.

Bài viết này sẽ giải thích cách tạo các truy vấn như vậy và cung cấp các ví dụ về các truy vấn SQL phức tạp.

Truy vấn phức tạp trông như thế nào?

Đầu tiên, hãy xác định các điều kiện để soạn truy vấn SQL. Đặc biệt, bạn sẽ cần sử dụng các tham số lựa chọn sau:

  • tên của các bảng mà bạn muốn trích xuất dữ liệu;
  • giá trị của các trường phải được trả về giá trị ban đầu sau khi thực hiện các thay đổi đối với cơ sở dữ liệu;
  • mối quan hệ giữa các bảng;
  • các điều kiện lấy mẫu;
  • các tiêu chí lựa chọn bổ sung (các hạn chế, cách trình bày thông tin, kiểu sắp xếp).

Để hiểu rõ hơn về chủ đề, hãy xem xét một ví dụ sử dụng bốn bảng đơn giản sau. Dòng đầu tiên là tên của bảng mà trong các truy vấn phức tạp đóng vai trò như một khóa ngoại. Chúng tôi sẽ xem xét điều này chi tiết hơn với một ví dụ:

Mỗi bảng có các hàng liên quan đến một số bảng khác. Chúng tôi sẽ giải thích lý do tại sao nó lại cần thiết.

Bây giờ, hãy xem truy vấn SQL cơ bản:

SELECT * FROM companies WHERE companies_name %STARTSWITH 'P';

% STARTSWITH vị ngữ chọn các hàng bắt đầu bằng ký tự / ký tự được chỉ định.

Kết quả như sau:

Bây giờ, hãy xem xét một truy vấn SQL phức tạp:

SELECT 
	companies.companies_name,
	SUM(CASE WHEN call.id IS NOT NULL THEN 1 ELSE 0 END) AS calls,
	AVG(ISNULL(DATEDIFF(SECOND, calls.start_time, calls.end_time),0)) AS avgdifference
FROM companies 
LEFT JOIN offices ON offices.companies_id = companies.id
LEFT JOIN customers ON offices.id = customers.offices_id
LEFT JOIN calls ON calls.customers_id = customers.id
GROUP BY 
	companies.id,
	companies.companies_name
HAVING AVG(ISNULL(DATEDIFF(SECOND, calls.start_time, calls.end_time),0)) > (SELECT AVG(DATEDIFF(SECOND, calls.start_time, calls.end_time)) FROM calls)
ORDER BY calls DESC, companies.id ASC;

Kết quả là bảng sau:

Bảng hiển thị các công ty, số lượng cuộc gọi điện thoại tương ứng và thời lượng gần đúng của họ.

Hơn nữa, nó chỉ liệt kê những tên công ty có thời lượng cuộc gọi trung bình lớn hơn thời lượng cuộc gọi trung bình ở các công ty khác.

Các quy tắc chính để tạo truy vấn SQL phức tạp là gì?

Hãy thử tạo một thuật toán đa năng để soạn các truy vấn phức tạp.

Trước hết, bạn cần quyết định các bảng chứa dữ liệu tham gia vào truy vấn.

Ví dụ trên liên quan đến công ty cuộc gọi những cái bàn. Nếu các bảng có dữ liệu bắt buộc không liên quan trực tiếp với nhau, bạn cũng cần bao gồm các bảng trung gian nối chúng.

Vì lý do này, chúng tôi cũng kết nối các bảng, chẳng hạn như văn phòng khách hàng , sử dụng khóa nước ngoài. Do đó, bất kỳ kết quả nào của truy vấn với các bảng từ ví dụ này sẽ luôn bao gồm các dòng dưới đây:

SELECT 
	...
FROM companies 
LEFT JOIN offices ON offices.companies_id = companies.id
LEFT JOIN customers ON offices.id = customers.offices_id
LEFT JOIN calls ON calls.customers_id = customers.id
...;

After that, you must test the correctness of the behavior in the following part of the query:

SELECT * FROM companies 
LEFT JOIN offices ON offices.companies_id = companies.id
LEFT JOIN customers ON offices.id = customers.offices_id
LEFT JOIN calls ON calls.customers_id = customers.id;

Một bảng kết hợp gợi ý ba điểm quan trọng nhất:

  • Chú ý đến danh sách các trường sau CHỌN. Thao tác đọc dữ liệu từ các bảng đã kết hợp yêu cầu bạn chỉ định tên của bảng được nối trong name lĩnh vực này.
  • Truy vấn phức tạp của bạn sẽ luôn có bảng chính ( công ty ). Hầu hết các trường được đọc từ nó. Bảng đính kèm, trong ví dụ của chúng tôi, sử dụng ba bảng - văn phòng , khách hàng cuộc gọi . Tên được xác định sau toán tử JOIN.
  • Ngoài việc chỉ định tên của bảng thứ hai, hãy nhớ chỉ định điều kiện để thực hiện phép nối. Chúng tôi sẽ thảo luận thêm về tình trạng này.
  • Truy vấn sẽ hiển thị một bảng có nhiều hàng. Không cần phải xuất bản nó ở đây, vì nó hiển thị kết quả trung gian. Tuy nhiên, bạn luôn có thể tự mình kiểm tra đầu ra của nó. Điều này rất quan trọng vì nó giúp tránh sai sót trong kết quả cuối cùng.

Bây giờ, hãy xem xét phần truy vấn so sánh thời lượng cuộc gọi trong mỗi công ty và giữa tất cả các công ty. Chúng ta cần tính thời lượng trung bình của tất cả các cuộc gọi. Sử dụng truy vấn sau:

SELECT AVG(DATEDIFF(SECOND, calls.start_time, calls.end_time)) FROM calls

Lưu ý rằng chúng tôi đã sử dụng DATEDIFF hàm tạo ra sự khác biệt giữa các khoảng thời gian được chỉ định. Trong trường hợp của chúng tôi, thời lượng cuộc gọi trung bình là 335 giây.

Bây giờ, hãy thêm dữ liệu về các cuộc gọi từ tất cả các công ty vào truy vấn.

SELECT 
	companies.companies_name,
	SUM(CASE WHEN calls.id IS NOT NULL THEN 1 ELSE 0 END) AS calls,
	AVG(ISNULL(DATEDIFF(SECOND, calls.start_time, calls.end_time),0)) AS avgdifference
FROM companies 
LEFT JOIN offices ON offices.companies_id = companies.id
LEFT JOIN customers ON offices.id = customers.offices_id
LEFT JOIN calls ON calls.customers_id = customers.id
GROUP BY 
	companies.id,
	companies.companies_name
ORDER BY calls DESC, companies.id ASC;

Trong truy vấn này,

  • SUM (TRƯỜNG HỢP KHI cuộc gọi. không phải là ĐẦY ĐỦ SAU 1 LẦN 0 KẾT THÚC) - để tránh các thao tác không cần thiết, chúng tôi chỉ tóm tắt các cuộc gọi hiện có - khi số lượng cuộc gọi trong một công ty không bằng 0. Điều này rất quan trọng trong các bảng lớn có thể có giá trị rỗng.
  • AVG (ISNULL (DATEDIFF (SECOND, call.start_time, call.end_time), 0)) - truy vấn giống với truy vấn AVG ở trên. Tuy nhiên, ở đây chúng tôi sử dụng ISNULL nhà điều hành thay thế NULL bằng 0. Điều này cần thiết cho các công ty không có cuộc gọi nào cả.

Kết quả của chúng tôi:

Chúng ta đang gần hoàn tất. Bảng trên trình bày danh sách các công ty, số lượng cuộc gọi tương ứng cho mỗi công ty và thời lượng cuộc gọi trung bình trong mỗi công ty.

Việc còn lại duy nhất là so sánh các số từ cột cuối cùng với thời lượng trung bình của tất cả các cuộc gọi từ tất cả các công ty (335 giây).

Nếu bạn nhập truy vấn mà chúng tôi đã trình bày ngay từ đầu, chỉ cần thêm HAVING một phần, bạn sẽ nhận được những gì bạn cần.

Chúng tôi thực sự khuyên bạn nên thêm nhận xét trên mỗi dòng để sau này bạn không bị nhầm lẫn khi cần sửa một số truy vấn SQL phức tạp hiện có.

Lời kết

Mặc dù mỗi truy vấn SQL phức tạp yêu cầu một cách tiếp cận riêng lẻ, một số khuyến nghị phù hợp cho việc chuẩn bị hầu hết các truy vấn như vậy.

  • xác định bảng nào sẽ tham gia vào truy vấn;
  • tạo các truy vấn phức tạp từ các phần đơn giản hơn;
  • kiểm tra độ chính xác của các truy vấn theo tuần tự, từng phần;
  • kiểm tra độ chính xác của truy vấn của bạn bằng các bảng nhỏ hơn;
  • viết nhận xét chi tiết trên mỗi dòng chứa toán hạng, sử dụng các ký hiệu ‘-‘.

Các công cụ chuyên dụng làm cho công việc này trở nên đơn giản hơn nhiều. Trong số đó, chúng tôi khuyên bạn nên sử dụng Trình tạo truy vấn - một công cụ trực quan cho phép tạo ngay cả những truy vấn phức tạp nhất nhanh hơn nhiều trong chế độ trực quan. Công cụ này có sẵn dưới dạng giải pháp độc lập hoặc là một phần của dbForge Studio đa tính năng dành cho SQL Server.

Chúng tôi hy vọng rằng bài viết này đã giúp bạn làm rõ vấn đề cụ thể này.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Cách hủy kích hoạt plugin từ cơ sở dữ liệu WordPress

  2. Sai lầm sơ đồ ER thường gặp

  3. Vấn đề Halloween - Phần 2

  4. Giới thiệu về Kích thước Thay đổi Từ từ (SCD)

  5. Mô hình dữ liệu nền tảng cho vay ngang hàng