• בלוג
  • יומי
  • סדרת SQL בסיסי - פוסט 20 - סיכום מידע לפי קבוצות

סדרת SQL בסיסי - פוסט 20 - סיכום מידע לפי קבוצות

29/08/2024

ראינו איך להפעיל פונקציות סיכום כדי לקבל ערך בודד מתוך אוסף של שורות. הרבה פעמים נרצה להפעיל את הסיכום רק על חלק מהשורות ובשביל זה יש לנו ב SQL את הפקודה GROUP BY.

1. ארגון העובדים לפי מחלקות

הפקודה GROUP BY ב SQL מאפשרת לחלק את השורות לקבוצות. באופן רגיל בתוך select בלוק זה יגרום להצגה רק של השורה הראשונה מכל קבוצה. לדוגמה השאילתה:

select * from employees group by department;

מחזירה את שלושת השורות:

id  name    city    department  salary
11  Diane   London  hr  70
21  Emma    London  it  84
31  Cindy   Berlin  sales   96

2. שילוב group by עם פונקציות סיכום

הכח של Group by הוא ביכולת לשלב את החלוקה לקבוצות עם פונקציות סיכום, וכך במקום לקבל רק את השורה הראשונה לכל קבוצה אנחנו יכולים לקבל סיכום אחר של ערכים. לדוגמה השאילתה הבאה תחזיר את שם המחלקה ואת המשכורת הממוצעת באותה מחלקה:

select department, avg(salary) from employees group by department;

באופן כללי בסיסי נתונים (חוץ מ SQLite) לא אוהבים שאתם מנסים להציג ב select עמודה שלא מופיעה ב group by, לכן הפקודה הבאה לא תעבוד:

select name, department, avg(salary) from employees group by department;

וזה הגיוני - כי לא ברור שם של איזה עובד צריך להציג.

כן אפשר לשלב מספר אגרגציות באותה שאילתה למשל זה עובד ומציג גם את המשכורת הממוצעת וגם את מספר העובדים בכל מחלקה:

select department, avg(salary), count(*) from employees group by department;

אפשר גם להפעיל מספר group by באותה פקודה לדוגמה הפקודה הבאה מציגה את המשכורת הממוצעת לפי עיר ומחלקה:

select *, avg(salary) from employees group by city, department;

3. הפקודה having

כמו שהיה לנו where כדי לבחור רק חלק מהשורות בפקודות select, כך כשהשורות מסודרות בקבוצות נשתמש בפקודת having כדי לבחור רק כאלה שפונקציית הסיכום מתאימה לתנאי מסוים. אפשר לחשוב על having כמו where של פונקציות סיכום.

לדוגמה אני יכול לעדכן את השאילתה הקודמת כדי שתחזיר רק את הקבוצות שמכילות יותר מעובד אחד (ובשביל לוודא שהכל עובד אני מוסיף גם את מספר העובדים לתוצאות):

select *, avg(salary), count(*) from employees group by city, department having count(*) > 1;