SQL มี VS ที่ไหน


202

ฉันมีสองตารางต่อไปนี้:

1. Lecturers (LectID, Fname, Lname, degree).
2. Lecturers_Specialization (LectID, Expertise).

ฉันต้องการหาอาจารย์ที่มีความเชี่ยวชาญมากที่สุด เมื่อฉันลองทำสิ่งนี้มันไม่ทำงาน:

SELECT
  L.LectID, 
  Fname, 
  Lname 
FROM Lecturers L, 
     Lecturers_Specialization S
WHERE L.LectID = S.LectID
AND COUNT(S.Expertise) >= ALL (SELECT
  COUNT(Expertise)
FROM Lecturers_Specialization
GROUP BY LectID);

แต่เมื่อฉันลองมันใช้งานได้:

SELECT
  L.LectID,
  Fname,
  Lname 
FROM Lecturers L,
     Lecturers_Specialization S
WHERE L.LectID = S.LectID
GROUP BY L.LectID,
         Fname,
         Lname 
HAVING COUNT(S.Expertise) >= ALL (SELECT
  COUNT(Expertise)
FROM Lecturers_Specialization
GROUP BY LectID); 

เหตุผลคืออะไร ขอบคุณ


2
คุณช่วยให้ชัดเจนว่าคุณใช้ SQL เวอร์ชันใด (MySQL, MS SQL, PostgreSQL, Oracle, ฯลฯ ) นอกจากนี้เมื่อคุณพูดว่า "ใช้งานไม่ได้" คุณหมายถึงผลลัพธ์ที่ไม่เป็นไปตามที่คุณคาดหวังหรือมีข้อผิดพลาดในการรวบรวม / แยกวิเคราะห์
jklemmack

2
ทำไมคุณถึงใช้ ALL แทน MAX? มีข้อได้เปรียบอะไรบ้าง?
skan

คำตอบ:


351

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

ตามกฎของหัวแม่มือให้ใช้WHEREก่อนGROUP BYและหลังHAVING GROUP BYมันเป็นกฎดั้งเดิม แต่มีประโยชน์มากกว่า 90% ของคดี

ในขณะที่คุณอยู่ในนั้นคุณอาจต้องการเขียนแบบสอบถามของคุณอีกครั้งโดยใช้รุ่นเข้าร่วม ANSI:

SELECT  L.LectID, Fname, Lname
FROM Lecturers L
JOIN Lecturers_Specialization S ON L.LectID=S.LectID
GROUP BY L.LectID, Fname, Lname
HAVING COUNT(S.Expertise)>=ALL
(SELECT COUNT(Expertise) FROM Lecturers_Specialization GROUP BY LectID)

นี้จะกำจัดWHEREที่ถูกนำมาใช้เป็นทีเข้าร่วมเงื่อนไข


39

HAVINGทำงานกับมวลรวม เนื่องจากCOUNTเป็นฟังก์ชั่นรวมคุณจึงไม่สามารถใช้งานได้ในWHEREประโยค

นี่คือการอ่านจาก MSDN ในฟังก์ชั่นรวม


30

อันดับแรกเราควรทราบลำดับการดำเนินการของ Clauses เช่น จาก> WHERE> GROUP BY> HAVING> DISTINCT> SELECT> ORDER BY เนื่องจากWHERE Clause ได้รับการดำเนินการก่อนGROUP BY Clause จึงไม่สามารถกรองข้อมูลได้โดยใช้WHEREกับGROUP โดยใช้เรคคอร์ด

"HAVING เหมือนกับ WHERE clause แต่ถูกใช้กับเร็กคอร์ดที่จัดกลุ่ม"

ก่อนอื่นส่วนคำสั่ง WHERE จะดึงข้อมูลตามเงื่อนไขจากนั้นส่วนกลุ่มตามส่วนคำสั่งจะจัดกลุ่มตามลำดับจากนั้นส่วนคำสั่งHAVING จะเรียกข้อมูลกลุ่มตามเงื่อนไขที่มีอยู่


คำสั่งนี้ใช้ในการดำเนินการเสมอหรือไม่ จะเกิดอะไรขึ้นหากเครื่องมือเพิ่มประสิทธิภาพคิวรีเปลี่ยนลำดับ
MSIS

1
@MSIS แม้ว่าเครื่องมือเพิ่มประสิทธิภาพคิวรีจะเปลี่ยนลำดับผลลัพธ์ก็ควรจะเหมือนกันกับว่ามีการติดตามคำสั่งซื้อนี้ มันเป็นลำดับตรรกะ
Stephen

18
  1. WHERE clause สามารถใช้กับคำสั่ง SELECT, INSERT และ UPDATE ได้ในขณะที่ HAVING สามารถใช้ได้กับคำสั่ง SELECT เท่านั้น

  2. ตัวกรองแถวก่อนหน้าการรวม (GROUP BY) ในขณะที่กลุ่มตัวกรอง HAVING หลังจากทำการรวม

  3. ฟังก์ชันการรวมไม่สามารถใช้ใน WHERE clause ได้ยกเว้นว่าจะอยู่ในแบบสอบถามย่อยที่มีอยู่ใน HAVING clause ในขณะที่ฟังก์ชันรวมสามารถใช้ใน HAVING clause ได้

แหล่ง


11

ไม่เห็นตัวอย่างของทั้งคู่ในข้อความค้นหาเดียว ตัวอย่างนี้อาจช่วยได้

  /**
INTERNATIONAL_ORDERS - table of orders by company by location by day
companyId, country, city, total, date
**/

SELECT country, city, sum(total) totalCityOrders 
FROM INTERNATIONAL_ORDERS with (nolock)
WHERE companyId = 884501253109
GROUP BY country, city
HAVING country = 'MX'
ORDER BY sum(total) DESC

วิธีนี้จะกรองตารางเป็นอันดับแรกโดย companyId จากนั้นจัดกลุ่ม (ตามประเทศและเมือง) แล้วกรองลงไปเป็นเพียงการรวมเมืองของเม็กซิโก companyId ไม่ต้องการในการรวม แต่เราสามารถใช้ WHERE เพื่อกรองเฉพาะแถวที่เราต้องการก่อนที่จะใช้ GROUP BY


มันไม่ได้เป็นตัวอย่างที่ดีอย่างที่คุณสามารถแปลงได้: `WHERE companyId = 884501253109 จัดกลุ่มตามประเทศเมืองที่มีประเทศ = 'MX' 'ถึง:' WHERE companyId = 884501253109 ประเทศ = 'MX' จัดกลุ่มตามเมือง '
Etienne Herlaut

หากเพียงแค่ย้าย [country] ตัวกรองไปยัง WHERE ที่คุณแนะนำการสืบค้นจะเกิดข้อผิดพลาดจาก SELECT [country] เนื่องจาก [country] ไม่รวมอยู่ในการรวม GROUP BY อีกต่อไปจึงไม่สามารถเลือกได้
Nhan

จุดของคุณเกี่ยวกับการปรับให้เหมาะสมนั้นจะถูกนำไปสู่การย้าย [ประเทศ] ไปที่ WHERE ซึ่งจะเป็นชุดข้อมูลขนาดเล็กลงไปที่ GROUP BY ในภายหลัง แน่นอนว่านี่เป็นเพียงตัวอย่างเพื่อแสดงให้เห็นถึงการใช้ที่เป็นไปได้ เราสามารถเปลี่ยนเป็น HAVING sum (total)> 1,000 และนั่นจะเป็นกรณีที่ถูกต้องสมบูรณ์ในการรวม WHERE และ HAVING
Nhan

9

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

แบบสอบถามตัวอย่าง:

select empName, sum(Bonus) 
from employees 
order by empName 
having sum(Bonus) > 5000;

สิ่งนี้จะเก็บชุดผลลัพธ์ไว้ในหน่วยความจำชั่วคราวจากนั้นการมีส่วนคำสั่งจะทำงานของมัน ดังนั้นเราสามารถใช้ฟังก์ชันการรวมที่นี่ได้อย่างง่ายดาย


2
ฉันคิดว่าเราไม่สามารถใช้ HAVING clause ได้หากไม่มี GROUP BY clause ตำแหน่งของคำสั่งย่อย - เลือก -> FROM -> WHERE -> GROUP BY -> HAVING -> ORDER BY
Morez

4

1. เราสามารถใช้ฟังก์ชันการรวมกับ HAVING clause ได้โดย WHERE clause เช่น min, max, avg

2. WHERE clause จะลบ tuple ของเร็กคอร์ดโดย tuple HAVING clause จะกำจัดทั้งกลุ่มออกจากกลุ่มของกลุ่ม

HAVING ส่วนใหญ่จะใช้เมื่อคุณมีกลุ่มข้อมูลและ WHERE จะถูกใช้เมื่อคุณมีข้อมูลเป็นแถว

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