2011-09-04 36 views
8

Trong ví dụ sau, tại sao kết quả trả về truy vấn min(), nhưng truy vấn max() thì không?Vấn đề hàm tổng hợp MySQL

mysql> create table t(id int, a int); 
Query OK, 0 rows affected (0.10 sec) 

mysql> insert into t(id, a) values(1, 1); 
Query OK, 1 row affected (0.03 sec) 

mysql> insert into t(id, a) values(1, 2); 
Query OK, 1 row affected (0.02 sec) 

mysql> select * from t 
    -> ; 
+------+------+ 
| id | a | 
+------+------+ 
| 1 | 1 | 
| 1 | 2 | 
+------+------+ 
2 rows in set (0.00 sec) 

mysql> select * from t where a < 4; 
+------+------+ 
| id | a | 
+------+------+ 
| 1 | 1 | 
| 1 | 2 | 
+------+------+ 
2 rows in set (0.00 sec) 

mysql> select * from t where a < 4 having a = max(a); 
Empty set (0.00 sec) 

mysql> select * from t where a < 4 having a = min(a); 
+------+------+ 
| id | a | 
+------+------+ 
| 1 | 1 | 
+------+------+ 
1 row in set (0.00 sec) 
+2

Truy vấn tất nhiên không hợp lệ trong tất cả các RDBMS khác. Bạn mong đợi điều gì để trở lại? –

Trả lời

7

Điều khoản HAVING được sử dụng để lọc các nhóm hàng. Bạn tham chiếu min(a)max(a) (trong trường hợp không có bất kỳ mệnh đề GROUP BY) tổng hợp trên tất cả các giá trị a trong bảng nhưng sau đó sử dụng so sánh với một giá trị a đơn lẻ.

Vì vậy, giá trị mà a là MySQL phải sử dụng? Tất cả các RDBMS khác mà tôi biết sẽ ném một lỗi vào thời điểm này tuy nhiên MySQL cho phép điều này. From the docs

chuẩn SQL không cho phép mệnh đề HAVING để đặt tên bất kỳ cột không tìm thấy trong mệnh đề GROUP BY trừ khi nó được bao trong một tổng chức năng. MySQL cho phép sử dụng các cột như vậy để đơn giản hóa các tính toán . Tiện ích mở rộng này giả định rằng các cột nongrouped sẽ có cùng giá trị nhóm. Nếu không, kết quả là không xác định.

Vì vậy, trong trường hợp của bạn từ kết quả mà bạn đang nhận được có vẻ như nó đã kết thúc bằng 1 như giá trị vô hướng cho a nhưng hành vi này không được bảo đảm và nó có thể tốt như nhau đã sử dụng 2 hoặc bất kỳ a khác hiện có giá trị.

+0

Và để chứng minh tính không xác định của kết quả, bạn có thể thêm một hàng có 'a = 0'. Bây giờ cả hai câu lệnh của bạn sẽ không trả lại hàng nào. – NullUserException

+2

Cách chính xác để làm điều này là sử dụng truy vấn phụ: 'select * from t where a = (chọn min (a) từ t);' – NullUserException

Các vấn đề liên quan