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

MYSQL hiển thị các hàng không chính xác khi sử dụng GROUP BY

Đây là một trở ngại kinh điển mà hầu hết các lập trình viên MySQL đều gặp phải.

  • Bạn có một cột ticket_id đó là đối số của GROUP BY . Các giá trị riêng biệt trong cột này xác định các nhóm.
  • Bạn có một cột incoming_time đó là đối số của MAX() . Giá trị lớn nhất trong cột này trên các hàng trong mỗi nhóm được trả về dưới dạng giá trị của MAX() .
  • Bạn có tất cả các cột khác của bài viết trong bảng. Các giá trị được trả về cho các cột này là tùy ý, không phải từ cùng một hàng có MAX() giá trị xảy ra.

Cơ sở dữ liệu không thể suy ra rằng bạn muốn các giá trị từ cùng một hàng nơi xuất hiện giá trị lớn nhất.

Hãy suy nghĩ về các trường hợp sau:

  • Có nhiều hàng xuất hiện cùng một giá trị tối đa. Hàng nào nên được sử dụng để hiển thị các cột của bài viết article.* ?

  • Bạn viết một truy vấn trả về cả MIN()MAX() . Điều này là hợp pháp, nhưng hàng nào nên article.* hiển thị?

    SELECT article.* , MIN(article.incoming_time), MAX(article.incoming_time)
    FROM ticket, article
    WHERE ticket.id = article.ticket_id
    AND ticket.queue_id = 1
    GROUP BY article.ticket_id
    
  • Bạn sử dụng một hàm tổng hợp chẳng hạn như AVG() hoặc SUM() , không có hàng nào có giá trị đó. Cơ sở dữ liệu làm cách nào để đoán hàng nào sẽ hiển thị?

    SELECT article.* , AVG(article.incoming_time)
    FROM ticket, article
    WHERE ticket.id = article.ticket_id
    AND ticket.queue_id = 1
    GROUP BY article.ticket_id
    

Trong hầu hết các thương hiệu cơ sở dữ liệu - cũng như bản thân tiêu chuẩn SQL - bạn không được phép để viết một truy vấn như thế này, vì sự không rõ ràng. Bạn không thể bao gồm bất kỳ cột nào trong danh sách chọn không nằm trong một hàm tổng hợp hoặc có tên trong GROUP BY mệnh đề.

MySQL dễ dãi hơn. Nó cho phép bạn làm điều này và để bạn viết các truy vấn mà không bị mơ hồ. Nếu bạn không rõ ràng, nó sẽ chọn các giá trị từ hàng vật lý đầu tiên trong nhóm (nhưng điều này tùy thuộc vào công cụ lưu trữ).

Đối với những gì nó đáng giá, SQLite cũng có hành vi này, nhưng nó chọn cuối cùng hàng trong nhóm để giải quyết sự không rõ ràng. Đi tìm con số. Nếu tiêu chuẩn SQL không cho biết phải làm gì, thì tùy thuộc vào việc triển khai của nhà cung cấp.

Đây là một truy vấn có thể giải quyết vấn đề của bạn cho bạn:

SELECT a1.* , a1.incoming_time AS maxtime
FROM ticket t JOIN article a1 ON (t.id = a1.ticket_id)
LEFT OUTER JOIN article a2 ON (t.id = a2.ticket_id 
  AND a1.incoming_time < a2.incoming_time)
WHERE t.queue_id = 1
  AND a2.ticket_id IS NULL;

Nói cách khác, hãy tìm một hàng (a1 ) mà không có hàng nào khác (a2 ) với cùng một ticket_idincoming_time lớn hơn . Nếu không có incoming_time lớn hơn được tìm thấy, LEFT OUTER JOIN trả về NULL thay vì khớp.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Đổi tên bảng trong MySQL

  2. Wampserver 2.1 có biểu tượng màu cam sau khi cài đặt trên Windows 7

  3. PHP MySQL nhận vị trí trong bán kính vị trí của người dùng từ GPS

  4. Khi nào sử dụng utf-8 và khi nào sử dụng latin1 trong MySQL?

  5. @GeneratedValue siêu lớp trừu tượng đa hình trên MySQL