ที่ไหนที่มี


247

ทำไมคุณต้องวางคอลัมน์ที่คุณสร้างเอง (เช่นselect 1 as "number") หลังHAVINGและไม่WHEREอยู่ใน MySQL?

และมีข้อเสียใด ๆ แทนการทำWHERE 1(เขียนคำจำกัดความทั้งหมดแทนชื่อคอลัมน์)?

คำตอบ:


323

ทำไมคุณต้องวางคอลัมน์ที่คุณสร้างขึ้นมาเอง (เช่น "เลือก 1 เป็นหมายเลข") หลังจากที่มีและไม่ใช่ที่ใน MySQL?

WHEREก่อนที่จะถูกนำไปใช้GROUP BY, HAVINGถูกนำไปใช้หลังจาก (และสามารถกรองมวลรวม)

โดยทั่วไปแล้วคุณสามารถอ้างอิงนามแฝงในค่าของคำสั่งเหล่านี้ แต่MySQLช่วยให้การอ้างอิงSELECTนามแฝงในระดับGROUP BY, และORDER BYHAVING

และจะมีข้อเสียใด ๆ แทนการทำ "WHERE 1" (เขียนคำจำกัดความทั้งหมดแทนชื่อคอลัมน์)

หากนิพจน์ที่คำนวณได้ของคุณไม่มีการรวมใด ๆ การวางลงในส่วนWHEREคำสั่งอาจมีประสิทธิภาพมากขึ้น


289

คำตอบอื่น ๆ ทั้งหมดสำหรับคำถามนี้ไม่ได้ตอบโจทย์ประเด็นสำคัญ

สมมติว่าเรามีโต๊ะ:

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

และมี 10 แถวที่มีทั้ง id และค่าจาก 1 ถึง 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);

ลอง 2 แบบสอบถามต่อไปนี้:

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

คุณจะได้ผลลัพธ์ที่เหมือนกันทุกประการคุณจะเห็นว่าส่วนคำสั่ง HAVING สามารถทำงานได้โดยไม่มี GROUP BY clause


นี่คือความแตกต่าง:

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

ข้อผิดพลาด # 1054 - คอลัมน์ที่ไม่รู้จัก 'v' ใน 'where clause'

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

ส่วนคำสั่ง WHERE อนุญาตให้เงื่อนไขใช้คอลัมน์ตารางใด ๆ แต่ไม่สามารถใช้นามแฝงหรือฟังก์ชันการรวม ส่วนคำสั่ง HAVING อนุญาตให้เงื่อนไขใช้คอลัมน์ (!) ที่เลือกไว้นามแฝงหรือฟังก์ชันการรวม

นี่เป็นเพราะ WHERE ส่วนคำสั่งกรองข้อมูลก่อนที่จะเลือก แต่ HAVING ข้อกรองผลข้อมูลหลังจากเลือก

ดังนั้นให้วางเงื่อนไขในส่วนคำสั่ง WHERE ซึ่งจะมีประสิทธิภาพมากกว่าถ้าคุณมีหลายแถวในตาราง

ลองอธิบายเพื่อดูความแตกต่างที่สำคัญ:

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 |
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+

คุณสามารถดูได้ว่า WHERE หรือ HAVING ใช้ดัชนี แต่แถวนั้นแตกต่างกัน


32
ฉันขอขอบคุณที่คุณพูดถึงอธิบาย!
paiego

เนื่องจาก HAVING clause กรองข้อมูลหลังจากเลือกแล้ว WHERE clause จะมีประสิทธิภาพมากกว่า ดังนั้นหากนี่เป็นความจริงเราต้องใช้ HAVING แทน WHERE เมื่อใด
grep

5
@grep ในกรณีที่คุณต้องกรองข้อมูลหลังจากที่เลือกคุณจำเป็นต้องมีประโยคโดยปกติเราจะใช้มันกับ GROUP BY clause เช่น: SELECT value, COUNT(*) frequency FROM table GROUP BY value HAVING frequency > 10
Fishdrowned

1
โพสต์ที่ยอดเยี่ยม คำชี้แจงที่แนะนำสอง...HAVING clause can use both column and alias....HAVING clause can use either column or alias....WHERE clause will be more effective...WHERE clause will be more efficient
ประการ

2
ส่วนคำสั่ง HAVING ถูกเพิ่มเข้าไปใน SQL เพราะไม่สามารถใช้คำสำคัญ WHERE กับฟังก์ชันการรวมได้
Shashank Vivek

62

ข้อแตกต่างที่สำคัญคือWHEREไม่สามารถใช้กับรายการที่จัดกลุ่ม (เช่นSUM(number)) โดยที่HAVINGสามารถทำได้

เหตุผลคือWHEREทำก่อนการจัดกลุ่มและHAVINGเสร็จหลังจากจัดกลุ่มเสร็จแล้ว


39

HAVINGGROUP BYจะใช้ในการกรองรวมตัวในของคุณ

ตัวอย่างเช่นหากต้องการตรวจสอบชื่อที่ซ้ำกัน:

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

1
มันเป็นความจริงสำหรับบางคนที่ยังหลงเหลืออยู่ คุณยังสามารถใส่ 'Where' ไว้ในประโยคที่มี
David Brunelle


8

ทั้งสองนี้จะรู้สึกเหมือนเป็นครั้งแรกที่ทั้งคู่ถูกใช้เพื่อกล่าวถึงเงื่อนไขในการกรองข้อมูล แม้ว่าเราสามารถใช้ 'มี' แทนที่ 'ที่ไหน' ในกรณีใด ๆ มีกรณีที่เราไม่สามารถใช้ 'ที่ไหน' แทน 'มี' นี่เป็นเพราะในแบบสอบถามแบบใช้เลือกข้อมูล 'ซึ่ง' กรองข้อมูลก่อน 'เลือก' ในขณะที่ 'มี' กรองข้อมูลหลังจาก 'เลือก' ดังนั้นเมื่อเราใช้ชื่อนามแฝงที่ไม่ได้อยู่ในฐานข้อมูล 'ที่' ไม่สามารถระบุได้ แต่ 'มี' สามารถ

ตัวอย่าง: ให้ตารางนักเรียนมี student_id, ชื่อ, วันเกิด, ที่อยู่วันเกิดสมมติว่าเป็นวันที่พิมพ์

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
ชีวิตจริงนี้ชี้แจงอย่างเต็มที่เช่นความแตกต่างระหว่างและWHERE HAVING
WM

แสดงให้เห็นอย่างชัดเจนถึงความแตกต่างระหว่างการมีและที่ไหน ขอบคุณ
MarcoZen

3

ตัวกรองWHEREก่อนที่ข้อมูลจะถูกจัดกลุ่มและตัวกรองHAVINGหลังจากข้อมูลถูกจัดกลุ่ม นี่คือความแตกต่างที่สำคัญ แถวที่ถูกกำจัดโดยส่วนคำสั่ง WHEREจะไม่รวมอยู่ในกลุ่ม สิ่งนี้สามารถเปลี่ยนค่าที่คำนวณได้ซึ่งในทางกลับกัน (= เป็นผลลัพธ์) อาจส่งผลต่อกลุ่มที่ถูกกรองตามการใช้ค่าเหล่านั้นในส่วน คำสั่งHAVING

และยังคง

การมีเพื่อให้คล้ายกับสถานที่ที่ DBMSs ที่สุดรักษาพวกเขาเป็นสิ่งเดียวกันหากไม่มีกลุ่มตามที่ระบุไว้ อย่างไรก็ตามคุณควรสร้างความแตกต่างด้วยตัวคุณเอง ใช้HAVINGร่วมกับGROUP BY clauses เท่านั้น ใช้WHEREสำหรับการกรองระดับแถวมาตรฐาน

ตัดตอนมาจาก: Forta, Ben “ แซมสอนตัวเอง SQL ใน 10 นาที (ฉบับที่ 5) (แซมซั่นสอนตัวเอง ... )”


1

มีการใช้เฉพาะกับการรวม แต่ที่มีงบไม่รวมหากคุณมีที่คำก่อนที่จะรวม (กลุ่มโดย)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.