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

Làm thế nào để GROUP BY trong MySQL đúng cách?

Điều đầu tiên cần làm rõ là SQL không phải là MySQL.

Trong SQL tiêu chuẩn, nó không được phép nhóm theo một tập con của các trường không được tổng hợp. Lý do rất đơn giản. Giả sử tôi đang chạy truy vấn này:

SELECT color, owner_name, COUNT(*) FROM cars
GROUP BY color

Truy vấn đó sẽ không có ý nghĩa gì. Ngay cả cố gắng giải thích nó sẽ là không thể. Chắc chắn nó đang chọn màu và đếm số lượng xe mỗi màu. Tuy nhiên, nó cũng đang thêm owner_name và có thể có nhiều chủ sở hữu cho một màu nhất định, như trường hợp của White màu sắc. Vì vậy, nếu có thể có nhiều owner_name các giá trị cho một color đây là trường duy nhất trong GROUP BY mệnh đề ... sau đó owner_name sẽ được trả lại?

Nếu cần trả lại owner_name thì một số loại tiêu chí sẽ được thêm vào để chỉ chọn một trong số chúng, ví dụ:tiêu chí đầu tiên theo thứ tự bảng chữ cái, trong trường hợp này sẽ là John . Tiêu chí đó sẽ dẫn đến việc thêm một hàm tổng hợp MIN(owner_name) và sau đó truy vấn sẽ có ý nghĩa trở lại vì nó sẽ được nhóm theo, ít nhất, tất cả các trường không được tổng hợp trong câu lệnh select.

Như bạn có thể thấy, có một lý do rõ ràng và thực tế cho việc SQL tiêu chuẩn không linh hoạt trong việc phân nhóm. Nếu không, bạn có thể gặp phải những tình huống khó xử trong đó giá trị của một cột sẽ không thể đoán trước được và đó không phải là một từ hay, đặc biệt nếu truy vấn đang chạy hiển thị cho bạn các giao dịch tài khoản ngân hàng của bạn.

Đã nói rằng, vậy tại sao MySQL lại cho phép các truy vấn có thể không có ý nghĩa? Và thậm chí tệ hơn, lỗi trong truy vấn ở trên có thể chỉ được phát hiện theo cú pháp! Câu trả lời ngắn gọn là:hiệu suất. Câu trả lời dài là có một số tình huống nhất định trong đó, dựa trên mối quan hệ dữ liệu, việc nhận một giá trị không thể đoán trước từ nhóm sẽ dẫn đến một giá trị có thể dự đoán được.

Nếu bạn chưa tìm ra, cách duy nhất để bạn có thể dự đoán giá trị mà bạn sẽ nhận được khi lấy một phần tử không thể đoán trước từ một nhóm sẽ là nếu tất cả các phần tử trong nhóm đều giống nhau. Một ví dụ rõ ràng về tình huống này là trong câu truy vấn mẫu trong câu hỏi tương tự của bạn. Xem cách owner_idowner_name liên quan trong bảng. Rõ ràng là đã cung cấp bất kỳ owner_id nào , ví dụ. 2 , bạn chỉ có thể có một owner_name riêng biệt . Ngay cả khi có nhiều hàng, bằng cách chọn bất kỳ hàng nào, bạn sẽ nhận được Mike kết quả là. Trong biệt ngữ cơ sở dữ liệu chính thức, điều này có thể được giải thích là owner_id xác định chức năng owner_name .

Hãy xem xét kỹ hơn truy vấn MySQL hoạt động đầy đủ đó:

SELECT owner_id, owner_name, COUNT(*) total FROM cars
GROUP BY owner_id

Đưa ra bất kỳ owner_id nào điều này sẽ trả về cùng một owner_name , vì vậy hãy thêm nó vào GROUP BY mệnh đề sẽ không dẫn đến nhiều hàng hơn được trả về. Thậm chí thêm một hàm tổng hợp MAX(owner_name) sẽ không dẫn đến việc trả về ít hàng hơn. Dữ liệu kết quả sẽ hoàn toàn giống nhau. Trong cả hai trường hợp, truy vấn sẽ ngay lập tức được chuyển thành truy vấn SQL chuẩn hợp pháp vì ít nhất tất cả các trường không tổng hợp sẽ được nhóm lại theo. Vì vậy, có 3 cách tiếp cận để có được kết quả tương tự.

Tuy nhiên, như tôi đã đề cập trước đây, nhóm không tiêu chuẩn này có một lợi thế về hiệu suất. Bạn có thể kiểm tra liên kết được đánh giá thấp này trong đó điều này được giải thích chi tiết hơn nhưng tôi sẽ trích dẫn phần quan trọng nhất:

Có một điều đáng nói là kết quả chưa chắc đã sai nhưng đúng hơn là không xác định . Nói cách khác, nhận được kết quả mong đợi không có nghĩa là bạn đã viết đúng truy vấn. Viết truy vấn phù hợp sẽ luôn mang lại cho bạn kết quả như mong đợi.

Như bạn thấy, có thể đáng giá khi áp dụng tiện ích mở rộng MySQL này cho GROUP BY mệnh đề. Dù sao, nếu điều này chưa rõ ràng 100% thì có một quy tắc chung sẽ đảm bảo rằng việc nhóm của bạn sẽ luôn đúng: Ít nhất, luôn nhóm theo tất cả các trường không được tổng hợp trong mệnh đề select . Bạn có thể lãng phí một vài chu kỳ CPU trong một số tình huống nhất định nhưng tốt hơn là trả về không xác định kết quả. Nếu bạn vẫn lo lắng về việc không nhóm đúng cách thì hãy thay đổi ONLY_FULL_GROUP_BY Chế độ SQL có thể là phương sách cuối cùng :)

Chúc cho nhóm của bạn đúng và hiệu quả ... hoặc ít nhất là đúng.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Làm thế nào để viết truy vấn SQL để tìm ra tổng của 4 cột cao nhất trong số 5 cột?

  2. Doctrine không tạo ra các ràng buộc khóa ngoài cơ sở dữ liệu chéo trong MySQL

  3. thiết kế cơ sở dữ liệu cho bài kiểm tra với các ngôn ngữ khác nhau

  4. SQL QUERY Sự cố sắp xếp kết quả

  5. Làm cách nào để thêm trình điều khiển JDBC vào đường dẫn Jenkins?