Ở ĐÂU vs HAVING


247

Tại sao bạn cần đặt các cột bạn tự tạo (ví dụ select 1 as "number") sau HAVINGvà không WHEREtrong MySQL?

Và có bất kỳ nhược điểm nào thay vì làm WHERE 1(viết toàn bộ định nghĩa thay vì tên cột) không?

Câu trả lời:


323

Tại sao bạn cần đặt các cột bạn tự tạo (ví dụ: "chọn 1 làm số") sau khi có HAVING chứ không phải WHERE trong MySQL?

WHEREđược áp dụng trước GROUP BY, HAVINGđược áp dụng sau (và có thể lọc trên tổng hợp).

Nói chung, bạn có thể tham khảo các bí danh tại không ai trong số các điều khoản này, nhưng MySQLcho phép tham khảo SELECTbí danh cấp GROUP BY, ORDER BYHAVING.

Và có bất kỳ nhược điểm nào thay vì thực hiện "WHERE 1" (viết toàn bộ định nghĩa thay vì tên cột)

Nếu biểu thức tính toán của bạn không chứa bất kỳ tổng hợp nào, việc đặt nó vào WHEREmệnh đề có thể sẽ hiệu quả hơn.


289

Tất cả các câu trả lời khác cho câu hỏi này không đánh vào điểm chính.

Giả sử chúng ta có một bảng:

CREATE TABLE `table` (
 `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 `value` int(10) unsigned NOT NULL,
 PRIMARY KEY (`id`),
 KEY `value` (`value`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

Và có 10 hàng với cả id và giá trị từ 1 đến 10:

INSERT INTO `table`(`id`, `value`) VALUES (1, 1),(2, 2),(3, 3),(4, 4),(5, 5),(6, 6),(7, 7),(8, 8),(9, 9),(10, 10);

Hãy thử 2 truy vấn sau:

SELECT `value` v FROM `table` WHERE `value`>5; -- Get 5 rows
SELECT `value` v FROM `table` HAVING `value`>5; -- Get 5 rows

Bạn sẽ nhận được kết quả chính xác như nhau, bạn có thể thấy mệnh đề HAVING có thể hoạt động mà không cần mệnh đề GROUP BY.


Đây là sự khác biệt:

SELECT `value` v FROM `table` WHERE `v`>5;

Lỗi # 1054 - Cột không xác định 'v' trong 'mệnh đề where'

SELECT `value` v FROM `table` HAVING `v`>5; -- Get 5 rows

Mệnh đề WHERE cho phép một điều kiện để sử dụng bất kỳ cột bảng nào, nhưng nó không thể sử dụng các bí danh hoặc các hàm tổng hợp. Mệnh đề HAVING cho phép một điều kiện để sử dụng cột (!) Đã chọn, bí danh hoặc hàm tổng hợp.

Điều này là do mệnh đề WHERE lọc dữ liệu trước khi chọn, nhưng mệnh đề HAVING lọc dữ liệu kết quả sau khi chọn.

Vì vậy, đặt các điều kiện trong mệnh đề WHERE sẽ hiệu quả hơn nếu bạn có nhiều hàng trong một bảng.

Hãy thử GIẢI THÍCH để thấy sự khác biệt chính:

EXPLAIN SELECT `value` v FROM `table` WHERE `value`>5;
+----+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+
| id | select_type | table | type  | possible_keys | key   | key_len | ref  | rows | Extra                    |
+----+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+
|  1 | SIMPLE      | table | range | value         | value | 4       | NULL |    5 | Using where; Using index |
+----+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+

EXPLAIN SELECT `value` v FROM `table` having `value`>5;
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key   | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+
|  1 | SIMPLE      | table | index | NULL          | value | 4       | NULL |   10 | Using index |
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+

Bạn có thể thấy WHERE hoặc HAVING sử dụng chỉ mục, nhưng các hàng khác nhau.


32
Tôi đánh giá cao rằng bạn đã đề cập GIẢI THÍCH!
paiego

Do mệnh đề HAVING lọc dữ liệu sau khi chọn, mệnh đề WHERE sẽ hiệu quả hơn. Vậy nếu điều này là đúng, khi nào chúng ta phải sử dụng HAVING thay vì WHERE?
grep

5
@grep Trong trường hợp bạn phải lọc dữ liệu sau khi chọn, bạn cần mệnh đề HAVING, thông thường chúng tôi sử dụng nó với mệnh đề GROUP BY, ví dụ: SELECT value, COUNT(*) frequency FROM table GROUP BY value HAVING frequency > 10
Fishdrown

1
Tuyệt vời bài. Một vài gợi ý làm rõ: Thay đổi ...HAVING clause can use both column and alias.để ...HAVING clause can use either column or alias.và thay đổi ...WHERE clause will be more effectiveđể...WHERE clause will be more efficient
rmirabelle

2
Mệnh đề HAVING đã được thêm vào SQL vì từ khóa WHERE không thể được sử dụng với các hàm tổng hợp.
Shashank Vivek

62

Sự khác biệt chính là WHEREkhông thể được sử dụng trên mục được nhóm (chẳng hạn như SUM(number)) trong khi HAVINGcó thể.

Lý do là WHEREđược thực hiện trước khi nhóm và HAVINGđược thực hiện sau khi nhóm được thực hiện.


39

HAVINGđược sử dụng để lọc trên các tập hợp trong của bạn GROUP BY.

Ví dụ: để kiểm tra tên trùng lặp:

SELECT Name FROM Usernames
GROUP BY Name
HAVING COUNT(*) > 1

1
Điều đó đúng với một số người còn tồn tại. Bạn vẫn có thể đặt toàn bộ 'Where' trong mệnh đề có.
David Brunelle


8

Cả hai sẽ có cảm giác giống như lần đầu tiên vì cả hai đều được sử dụng để nói về một điều kiện để lọc dữ liệu. Mặc dù chúng ta có thể sử dụng 'có' thay cho 'nơi' trong mọi trường hợp, có những trường hợp khi chúng ta không thể sử dụng 'nơi' thay vì 'có'. Điều này là do trong một truy vấn chọn, 'trong đó' lọc dữ liệu trước 'select' trong khi 'có' dữ liệu lọc sau 'select'. Vì vậy, khi chúng tôi sử dụng các tên bí danh không thực sự có trong cơ sở dữ liệu, 'nơi' không thể xác định chúng nhưng 'có' có thể.

Ví dụ: hãy để bảng Sinh viên chứa student_id, tên, sinh nhật, địa chỉ. Sinh nhật là loại ngày.

SELECT * FROM Student WHERE YEAR(birthday)>1993; /*this will work as birthday is in database.if we use having in place of where too this will work*/

SELECT student_id,(YEAR(CurDate())-YEAR(birthday)) AS Age FROM Student HAVING Age>20; 
/*this will not work if we use ‘where’ here, ‘where’ don’t know about age as age is defined in select part.*/

1
Ví dụ thực tế này làm rõ đầy đủ sự khác biệt giữa WHEREHAVING.
WM

Rõ ràng cho thấy sự khác biệt giữa Có và ở đâu. Cảm ơn.
MarcoZen

3

Bộ lọc WHERE trước khi dữ liệu được nhóm và HAVING bộ lọc sau khi dữ liệu được nhóm. Đây là một dấu hiệu đặc biệt quan trọng; các hàng bị loại bỏ bởi mệnh đề WHERE sẽ không được đưa vào nhóm. Điều này có thể thay đổi các giá trị được tính toán, lần lượt (= kết quả) có thể ảnh hưởng đến các nhóm được lọc dựa trên việc sử dụng các giá trị đó trong mệnh đề HAVING .

Và tiếp tục,

HAVING tương tự như WHERE đến nỗi hầu hết các DBMS đều coi chúng là điều tương tự nếu không có NHÓM THEO nào được chỉ định. Tuy nhiên, bạn nên làm cho sự khác biệt đó chính mình. Chỉ sử dụng HAVING kết hợp với mệnh đề NHÓM THEO . Sử dụng WHERE để lọc mức hàng tiêu chuẩn.

Trích từ: Forta, Ben. Sams tự dạy mình SQL trong 10 phút (Phiên bản thứ 5) (Sams tự dạy mình ...).


1

Có chỉ được sử dụng với tổng hợp nhưng ở đâu với các câu lệnh không tổng hợp Nếu bạn có từ đặt nó trước khi tổng hợp (nhóm theo)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.