Câu trả lời:
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 MySQL
cho phép tham khảo SELECT
bí danh cấp GROUP BY
, ORDER BY
và HAVING
.
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 WHERE
mệnh đề có thể sẽ hiệu quả hơn.
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.
SELECT value, COUNT(*) frequency FROM table GROUP BY value HAVING frequency > 10
...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
Sự khác biệt chính là WHERE
không thể được sử dụng trên mục được nhóm (chẳng hạn như SUM(number)
) trong khi HAVING
có 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.
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
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.*/
WHERE
và HAVING
.
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 ...).
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)