อะไรคือความแตกต่างระหว่าง HAVING และ WHERE?


261

ฉันจะต้องไปในทางที่ผิดหรือฉันกำลังโง่ในเวลา

ความแตกต่างระหว่างHAVINGและWHEREในSQL SELECTคำสั่งคืออะไร?

แก้ไข: ฉันได้ทำเครื่องหมายคำตอบของสตีเวนว่าเป็นคำตอบที่ถูกต้องเนื่องจากมีข้อมูลบิตหลักในลิงค์:

เมื่อGROUP BYไม่ได้ใช้งานHAVINGจะทำงานเหมือนWHEREประโยค

สถานการณ์ที่ฉันเห็นWHEREในไม่มีGROUP BYและเป็นที่ที่ฉันเริ่มสับสน แน่นอนจนกว่าคุณจะรู้สิ่งนี้คุณไม่สามารถระบุได้ในคำถาม


44
บรรทัดที่คุณพูดไม่ใช่บิตหลักเลย บิตคีย์ดังที่ wcm ชี้ให้เห็นคือHAVINGตัวกรองหลังการรวมขณะที่WHEREเป็นตัวกรองการรวมล่วงหน้า
Nick Chammas

ลิงค์นี้ช่วยให้ฉันเข้าใจดีกว่าความคิดเห็นทั้งหมดด้านล่างคิดว่าบางคนสามารถรับความช่วยเหลือจากcodeproject.com/Articles/25258/
Lijin Durairaj

คำตอบ:



369

HAVING: ใช้เพื่อตรวจสอบเงื่อนไขหลังจากการรวมเกิดขึ้น
WHERE: ใช้เพื่อตรวจสอบเงื่อนไขก่อนการรวมเกิดขึ้น

รหัสนี้:

select City, CNT=Count(1)
From Address
Where State = 'MA'
Group By City

ให้ตารางของเมืองทั้งหมดใน MA และจำนวนที่อยู่ในแต่ละเมือง

รหัสนี้:

select City, CNT=Count(1)
From Address
Where State = 'MA'
Group By City
Having Count(1)>5

ให้ตารางเมืองใน MA ที่มีมากกว่า 5 ที่อยู่และจำนวนที่อยู่ในแต่ละเมือง


7
นี่ควรเป็นคำตอบที่ยอมรับได้ ความแตกต่างระหว่าง "มี" และ "ที่ไหน" ทำให้ชัดเจนทันที
พอล

27

ความแตกต่างอันดับหนึ่งสำหรับฉัน: ถ้าHAVINGถูกลบออกจากภาษา SQL ชีวิตจะมีมากขึ้นหรือน้อยลงเหมือนเมื่อก่อน แน่นอนว่าคำสั่งของผู้ถือหุ้นส่วนน้อยจะต้องถูกเขียนใหม่โดยใช้ตารางที่ได้รับ CTE และอื่น ๆ แต่พวกเขาจะเข้าใจและบำรุงรักษาได้ง่ายขึ้น อาจต้องใช้รหัสเครื่องมือเพิ่มประสิทธิภาพของผู้ขายเพื่อเขียนใหม่สำหรับบัญชีนี้เป็นโอกาสในการปรับปรุงภายในอุตสาหกรรมอีกครั้ง

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

TL; DR เราอาจแพ้HAVINGในวันพรุ่งนี้และทุกอย่างจะไม่แย่ไปกว่านั้นอาจจะดีกว่า แต่ก็ไม่สามารถพูดWHEREได้เหมือนกัน


จากคำตอบที่นี่ดูเหมือนว่าชาวบ้านจำนวนมากไม่ตระหนักว่าHAVINGอาจมีการใช้GROUP BYประโยคโดยไม่มีประโยค ในกรณีนี้HAVINGคำสั่งจะถูกนำไปใช้กับการแสดงออกของตารางทั้งหมดและต้องการให้ค่าคงที่เท่านั้นปรากฏในส่วนSELECTคำสั่ง โดยทั่วไปHAVINGข้อจะเกี่ยวข้องกับมวลรวม

สิ่งนี้มีประโยชน์มากกว่าที่คิด ตัวอย่างเช่นลองพิจารณาแบบสอบถามนี้เพื่อทดสอบว่าnameคอลัมน์นั้นมีค่าเฉพาะสำหรับทุกค่าในT:

SELECT 1 AS result
  FROM T
HAVING COUNT( DISTINCT name ) = COUNT( name );

มีเพียงสองผลลัพธ์ที่เป็นไปได้: หากส่วนHAVINGคำสั่งเป็นจริงผลลัพธ์จะเป็นแถวเดียวที่มีค่า1มิฉะนั้นผลลัพธ์จะเป็นชุดว่าง


นั่นจะเทียบเท่ากับ "SELECT COUNT (DISTINCT name) = COUNT (ชื่อ) จาก T" หรือไม่
MSpreij

@MSpreij ไม่ทราบว่าเหมาะกับคุณหรือไม่ แต่ไม่สามารถใช้กับ SQL Server 2005 ได้ แต่ตัวแรกจะใช้งานได้
Joe

22

ส่วนคำสั่ง HAVING ถูกเพิ่มไปยัง SQL เนื่องจากไม่สามารถใช้คีย์เวิร์ด WHERE กับฟังก์ชันรวมได้

ตรวจสอบลิงค์ w3schoolsนี้สำหรับข้อมูลเพิ่มเติม

ไวยากรณ์:

SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name
HAVING aggregate_function(column_name) operator value

แบบสอบถามเช่นนี้:

SELECT column_name, COUNT( column_name ) AS column_name_tally
  FROM table_name
 WHERE column_name < 3
 GROUP 
    BY column_name
HAVING COUNT( column_name ) >= 3;

... อาจถูกเขียนใหม่โดยใช้ตารางที่ได้รับ (และละเว้นHAVING) ดังนี้:

SELECT column_name, column_name_tally
  FROM (
        SELECT column_name, COUNT(column_name) AS column_name_tally
          FROM table_name
         WHERE column_name < 3
         GROUP 
            BY column_name
       ) pointless_range_variable_required_here
 WHERE column_name_tally >= 3;

3
คุณเคยพลาดเล็กน้อยจุด: HAVINGถูกบันทึกเพราะตารางมาไม่เคยได้รับการเพิ่มภาษาและจนกว่าพวกเขาจะ SQL ยังไม่เสร็จสมบูรณ์ relationally และเมื่อพวกเขาอย่างหลีกเลี่ยงไม่ได้รับการHAVINGซ้ำซ้อน
onedaywhen

21

ความแตกต่างระหว่างทั้งสองอยู่ในความสัมพันธ์กับกลุ่มตามข้อ:

  • ที่ไหนมาก่อนกลุ่มตาม; SQL จะประเมิน WHERE clause ก่อนที่จะจัดกลุ่มเรกคอร์ด

  • มีหลังจากกลุ่มตาม; SQL ประเมิน HAVING หลังจากจัดกลุ่มเร็กคอร์ด

เลือกไดอะแกรมคำสั่ง

อ้างอิง


เนื่องจาก GROUP BY และ HAVING เป็นตัวเลือกไดอะแกรมแสดงทั้งสองกรณีเพียงทำตามลูกศร
Paul Sweatte

แบบสอบถามตัวอย่างจากคำตอบของฉันคำถามนี้: SELECT 1 AS result FROM T HAVING...- ในแผนภาพของคุณฉันไม่สามารถรับไปHAVINGโดยไม่ผ่านแต่แบบสอบถามถูกต้องสมบูรณ์และเป็นประโยชน์ของฉันไม่มีGROUP BY GROUP BYจุดเล็กน้อย: คุณไม่มีตัวเลือกในการรวมค่าตามตัวอักษรในSELECTข้อ
เมื่อ

@onedaywhen เมื่อคุณรู้เกี่ยวกับการบอกเป็นนัย GROUP BY ทำไมคุณไม่พูดถึงมัน? คุณรู้หรือไม่ว่าพฤติกรรมนี้เป็นสิ่งที่คุณคาดหวังหรือไม่
Paul Sweatte

คิดว่าคุณกำลังอ้างฉันจากบริบท คำถามคือเกี่ยวกับความเบี่ยงเบนที่เห็นได้ชัดของ mySQL จากมาตรฐานทั้งหมด แต่ย่อหน้าสุดท้ายของคำตอบของฉันอธิบายถึงพฤติกรรมมาตรฐานและสุดท้ายหมายถึง "กลุ่มโดยนัยตามข้อที่กล่าวถึงในคำตอบอื่น ๆ " คุณกำลังบอกว่าแผนภาพของคุณมีวัตถุประสงค์เพื่ออธิบายพฤติกรรมทั้งหมด มันจะมีประโยชน์มากกว่าถ้าคุณใช้โค้ดที่คุณต้องการเขียนเพื่อให้ได้พฤติกรรมที่ต้องการหรือไม่
oneday เมื่อ

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

12

HAVINGGROUP BYจะใช้เมื่อคุณกำลังใช้รวมกันเช่น

SELECT edc_country, COUNT(*)
FROM Ed_Centers
GROUP BY edc_country
HAVING COUNT(*) > 1
ORDER BY edc_country;

8

WHERE จะถูกใช้เป็นข้อ จำกัด ของชุดที่ส่งคืนโดย SQL; มันใช้การตั้งค่าในตัวของ Oeprations และดัชนีของ SQL ดังนั้นจึงเป็นวิธีที่เร็วที่สุดในการกรองชุดผลลัพธ์ ใช้ WHERE ทุกครั้งที่ทำได้

จำเป็นต้องมีตัวกรองรวมบางตัว มันกรองแบบสอบถามหลังจาก sql ได้ดึงรวบรวมและเรียงลำดับผลลัพธ์ ดังนั้นจึงช้ากว่า WHERE มากและควรหลีกเลี่ยงยกเว้นในสถานการณ์ที่จำเป็นต้องใช้

SQL Server จะช่วยให้คุณไม่ต้องใช้ HAVING แม้ในเวลาที่ว่าที่ไหนจะเร็วขึ้น อย่าทำมัน


การสนับสนุนตารางที่ได้รับในภาษา SQL หมายถึงการยืนยันของคุณ "การมีความจำเป็นสำหรับตัวกรองสรุป" เป็นเท็จ
onedaywhen

1
นั่นเป็นจุดที่ดี ในช่วงสามปีที่ผ่านมาฉันเขียนคำตอบนี้ฉันได้ย้ายไปใช้ตารางที่เคยใช้มาก่อนแล้ว ฉันไม่ได้คิดถึงคำถามที่ว่า HAVING ยังคงมีกรณีการใช้งานบางอย่างที่สมเหตุสมผล ฉันเองก็ไม่รู้เหมือนกันว่าตารางที่ได้รับนั้นจะทำงานได้ดีกว่าการมี
davidcl

7

คำสั่ง WHERE ไม่ทำงานสำหรับฟังก์ชั่นรวม
หมายถึง: คุณไม่ควรใช้เช่นโบนัสนี้: ชื่อตาราง

SELECT name  
FROM bonus  
GROUP BY name  
WHERE sum(salary) > 200  

ที่นี่แทนที่จะใช้คำสั่ง WHERE คุณต้องใช้ HAVING ..

โดยไม่ใช้ GROUP BY clause ข้อ HAVING จะทำงานเป็น WHERE clause ได้

SELECT name  
FROM bonus  
GROUP BY name  
HAVING sum(salary) > 200  

4

ความแตกต่าง b / w WHEREและHAVINGข้อ:

ความแตกต่างที่สำคัญระหว่างWHEREและHAVINGข้อคือWHEREใช้สำหรับการดำเนินงานแถวและHAVINGใช้สำหรับการดำเนินงานคอลัมน์

ทำไมเราต้องมีHAVINGประโยค?

ดังที่เราทราบฟังก์ชันรวมสามารถทำได้ในคอลัมน์เท่านั้นดังนั้นเราจึงไม่สามารถใช้ฟังก์ชันรวมได้ในWHEREข้อ ดังนั้นเราจึงใช้ฟังก์ชั่นรวมในHAVINGข้อ


2

เมื่อGROUP BYไม่ได้ใช้งานคำสั่งWHEREและHAVINGcluster จะเทียบเท่ากันเป็นหลัก

อย่างไรก็ตามเมื่อGROUP BYใช้:

  • ส่วนWHEREคำสั่งที่ใช้ในการกรองบันทึกจากผลลัพธ์ การกรองเกิดขึ้นก่อนการจัดกลุ่มใด ๆ
  • ส่วนHAVINGคำสั่งที่ใช้ในการกรองค่าจากกลุ่ม (เช่นเพื่อตรวจสอบเงื่อนไขหลังจากการรวมเป็นกลุ่มได้รับการดำเนินการ)

ทรัพยากรจากที่นี่


มีและที่ไม่เทียบเท่าหลัก มันจะให้ข้อผิดพลาดขณะดำเนินการ ไม่ถูกต้องใน HAVING clause เนื่องจากไม่มีอยู่ในฟังก์ชันการรวมหรือ GROUP BY clause
Nagendra Kumar

2

วิธีคิดอย่างหนึ่งคือการมีส่วนคำสั่งเป็นตัวกรองเพิ่มเติมไปยังส่วนคำสั่งที่

ส่วนคำสั่ง WHEREจะใช้ตัวกรองระเบียนจากผลลัพธ์ ตัวกรองเกิดขึ้นก่อนที่จะจัดกลุ่มใด ๆ ส่วนคำสั่งHAVINGใช้เพื่อกรองค่าจากกลุ่ม


1

ในแบบสอบถามแบบรวม (แบบสอบถามใด ๆ ที่มีการใช้ฟังก์ชันการรวม) การคาดคะเนว่าคำสั่งย่อยใดถูกประเมินก่อนที่จะสร้างชุดผลลัพธ์กลางที่รวบรวมไว้

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


1

ฉันมีปัญหาและพบความแตกต่างระหว่างWHEREและHAVINGอีก มันไม่ได้ทำในลักษณะเดียวกันกับคอลัมน์ที่จัดทำดัชนี

WHERE my_indexed_row = 123 จะแสดงแถวและดำเนินการ "สั่งซื้อ ASC" โดยอัตโนมัติในแถวที่จัดทำดัชนีอื่น ๆ

HAVING my_indexed_row = 123 แสดงทุกอย่างจากแถว "แทรก" ที่เก่าแก่ที่สุดไปยังแถวใหม่ล่าสุดโดยไม่มีการสั่งซื้อ


คุณจะรู้ได้อย่างไรว่านี่เป็นความแตกต่างที่กำหนดไว้ระหว่างทั้งสองไม่ใช่อุบัติเหตุของการใช้งานเซิร์ฟเวอร์ SQL เฉพาะที่คุณใช้งานอยู่
JdeBP

ฉันเพิ่งทดสอบมันบน MariaDB ฉันเดาว่าเป็นเซิร์ฟเวอร์ SQL ที่ฉันใช้เมื่อ 8 ปีก่อนซึ่งให้ผลลัพธ์ที่แตกต่างกัน
Simmoniz

0

จากที่นี่

มาตรฐาน SQL ต้องการให้ HAVING ต้องอ้างอิงเฉพาะคอลัมน์ในกลุ่มตามข้อหรือคอลัมน์ที่ใช้ในฟังก์ชั่นรวม

ตรงข้ามกับส่วนคำสั่ง WHERE ซึ่งใช้กับแถวฐานข้อมูล


ที่มากล่าวว่า "การใช้ตำแหน่งคอลัมน์ถูกคัดค้านเนื่องจากไวยากรณ์ถูกลบออกจากมาตรฐาน SQL" น่าเศร้านี่เป็นความผิด: ไม่มีสิ่งใดถูกลบออกจากมาตรฐานซึ่งเป็นเรื่องน่าขันว่าทำไมเรายังมีอีกHAVINGหลายสิบปีหลังจากที่มันถูก 'เลิก' โดยตารางที่ได้รับ
onedaywhen

คำพูดเล็กน้อย แต่พูดไม่ถูกต้องเช่นพิจารณาSELECT 1 FROM T HAVING COUNT(*) >= 1;- ไม่ได้อ้างอิงคอลัมน์ในส่วนGROUP BYคำสั่ง (ไม่มี) และคอลัมน์ในฟังก์ชั่นรวม (แบบสอบถามอ้างอิงไม่มีคอลัมน์เลย)
onedaywhen

0

ในขณะที่ทำงานในโครงการนี่คือคำถามของฉัน ตามที่ระบุไว้ข้างต้นHAVINGตรวจสอบเงื่อนไขในผลการสืบค้นที่พบแล้ว แต่WHEREสำหรับเงื่อนไขการตรวจสอบในขณะที่วิ่งแบบสอบถาม

ผมขอยกตัวอย่างเพื่ออธิบายสิ่งนี้ สมมติว่าคุณมีตารางฐานข้อมูลเช่นนี้

ใช้งานได้ {ผู้ใช้ int, Datefield Date, Int Dailyincome}

สมมติว่าแถวต่อไปนี้อยู่ในตาราง:

1, 2011-05-20, 100

1, 2011-05-21, 50

1, 2011-05-30, 10

2, 2011-05-30, 10

2, 2011-05-20, 20

ตอนนี้เราต้องการได้userids และsum(dailyincome)ใครsum(dailyincome)>100

ถ้าเราเขียน:

เลือกหมายเลขผู้ใช้ผลรวม (Dailyincome) จากการใช้งานได้ทุกที่ (รวมทุกวัน)> 100 กลุ่มตามหมายเลขผู้ใช้

นี่จะเป็นข้อผิดพลาด แบบสอบถามที่ถูกต้องจะเป็น:

เลือกหมายเลขผู้ใช้ผลรวม (Dailyincome) จากกลุ่มที่ใช้งานได้ง่ายโดยรวมหมายเลขผู้ใช้ที่มี (ทุกวัน)> 100


0

WHERE clause ใช้สำหรับการเปรียบเทียบค่าในตารางพื้นฐานในขณะที่ HAVING clause สามารถใช้สำหรับกรองผลลัพธ์ของฟังก์ชันการรวมในชุดผลลัพธ์ของแบบสอบถามคลิกที่นี่ !


0

เมื่อ GROUP BY ไม่ได้ใช้คำสั่ง WHERE และ HAVING จะเทียบเท่ากันเป็นหลัก

อย่างไรก็ตามเมื่อใช้ GROUP BY:

  • ส่วนคำสั่ง WHERE จะใช้เพื่อกรองระเบียนจากผลลัพธ์ การกรองเกิดขึ้นก่อนการจัดกลุ่มใด ๆ
  • ส่วนคำสั่ง HAVING ใช้เพื่อกรองค่าจากกลุ่ม (เช่นเพื่อตรวจสอบเงื่อนไขหลังจากทำการรวมเข้าไปในกลุ่ม)

-1

ฉันใช้ HAVING เพื่อ จำกัด การสืบค้นตามผลลัพธ์ของฟังก์ชันการรวม EG เลือก * ในกลุ่ม blahblahblah โดย SOMETHING มีจำนวน (SOMETHING)> 0


-1

อาจเป็นได้ว่าหัวเรื่องของ "ที่ไหน" เป็นแถวในขณะที่หัวเรื่องของ "การมี" เป็นกลุ่ม ฉันถูกไหม?


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