שיעורי מודול (4/4)
קבוצות סינון: HAVING
ברגע שיש לך תוצאה לכל קבוצה (שיעור קודם), אתה לרוב רוצה
שמור רק את הקבוצות שמקיימות תנאי: מחלקות עם יותר
מ-2 אנשים, פרויקטים עם תקציב ממוצע מעל 100,000, משתמשים עם
לפחות 10 הזמנות. כדי לעשות זאת WHERE לא מספיק.
למה WHERE לא מספיק
WHERE מסנן את שורות הטבלה, לפני צבירה. אז זה לא יכול לראות
התוצאה של COUNT(*) או AVG(...): עד להפעלת WHERE, אלה
הערכים עדיין לא חושבו.
-- ERROR: COUNT(*) doesn't exist yet when WHERE is evaluated
SELECT department_id, COUNT(*) AS count
FROM employees
WHERE COUNT(*) > 2 -- ❌ doesn't work
GROUP BY department_id;כדי לסנן לאחר צבירה, יש סעיף ייעודי: HAVING.
התחביר
SELECT grouping_column, AGGREGATE_FUNCTION(...)
FROM table
GROUP BY grouping_column
HAVING condition_on_aggregate;-- Departments with more than 2 employees:
SELECT department_id, COUNT(*) AS count
FROM employees
GROUP BY department_id
HAVING COUNT(*) > 2;HAVING הוא GROUP BY מה שWHERE הוא לFROM: אותו רעיון
("מסנן"), אך הוחל לאחר קיבוץ, במצטבר.
הסדר ההגיוני של הסעיפים
כדי לעולם לא לבלבל שוב את WHERE וHAVING, זכור את הסדר שבו
SQL מבצע אותם מנטלית:
FROM/JOIN- בונה את טבלת ההתחלה על ידי צירוף מקורות.WHERE- מוריד את השורות שלא אכפת לך מהן.GROUP BY- אוסף את השורות הנותרות לקבוצות.HAVING- מוריד את הקבוצות שלא אכפת לך מהן.SELECT- מחשב את העמודות הסופיות (כולל אגרגטים).ORDER BY/LIMIT- סדר מחדש וחתוך.
הערות חשובות:
- ב-
WHEREאתה יכול להשתמש רק בעמודות טבלה; - ב-
HAVINGאתה יכול להשתמש ב-קיבוץ עמודות ומצטברים.
-- Classic combo: filter first, group, filter the groups, sort.
SELECT d.name, AVG(e.salary) AS average
FROM employees AS e
JOIN departments AS d ON e.department_id = d.id
WHERE e.hired_on >= '2018-01-01' -- filter rows
GROUP BY d.name
HAVING AVG(e.salary) > 35000 -- filter groups
ORDER BY average DESC;נסה את זה
עבור כל מחלקה, הצג את השם (departments.name) ואת ספירת העובדים, אך רק עבור מחלקות עם לפחות 2 עובדים. שתי עמודות, שורה אחת לכל מחלקה מזכה.
הצג רמז
התנאי 'לפחות 2' הופך ל-COUNT(*) >= 2 ב-HAVING.
הפתרון זמין לאחר 3 ניסיונות
סקירת התרגיל
הצג את המחלקות (departments.name) שהשכר הממוצע שלהן עולה על 35000. קחו בחשבון רק עובדים שנקלטו משנת 2018 ואילך. שתי עמודות: שם וממוצע. מיין לפי ממוצע יורד.
הצג רמז
WHERE מסנן את השורות (עובדים שנקלטו משנת 2018), HAVING מסנן את הקבוצות (ממוצע > 35000).
הפתרון זמין לאחר 3 ניסיונות