בשפת SQL קיים מגוון של פונקציות אגרגציה שניתן להשתמש בהם על מנת להחזיר תוצאות חישוב על עמודות בטבלאות. נוכל להשתמש ב-GROUP BY על מנת להשתמש בפונקציות אלו על קבוצות מסוימות מתוך הטבלה
פונקציות אגרגציה
בין פונקציות האגרגציה אשר קיימות בשפת SQL ניתן למצוא מגוון של פונקציות חשובות אשר נוכל להשתמש בהם על מנת לבצע חישובים, למשל:
- COUNT – יחזיר לנו את מספר השורות של העמודה
- SUM – יחזיר לנו את סכום החיבור של כל הערכים מעמודה מסוימת
- MIN ו-MAX – יחזירו את הערך הגבוה או הנמוך ביותר מהעמודה בהתאמה.
- AVG – יחזיר לנו את הממוצע של הערכים מהעמודה
SQL GROUP BY
ב-GROUP BY ניתן להשתמש על מנת לקבץ שורות רבות לשורה בודדת, בדומה ל-DISTINCT.
לשם ההדגמה נשתמש במסד הנתונים AdventureWorks sample databases אשר ניתן להורדה.
שימו לב לטבלה הבאה שנלקחה מתוך מסד נתונים זה:
אם נרצה לדוגמא לקבץ לפי עיר וננסה להריץ את השאילתה הבאה:
SELECT TOP (1000) * FROM SalesLT.Address GROUP BY City
כמובן שנקבל שגיאה, מהסיבה שה-SELECT ינסה להציג את כל העמודות בזמן שה-GROUP BY מתייחס לאחת מהן בלבד.
יכולנו למשל לבקש רק את העמודה City, ואז לא היינו נתקלים בבעיה:
SELECT TOP (1000) City FROM SalesLT.Address GROUP BY City
אך היינו מקבלים טבלה בעלת עמודה אחת, וזה בהחלט לא מה שרצינו לקבל.
אך אם נרצה לקבץ את הטבלה לפי עיר, כך שמכל עיר תוצג רשומה אחת (המשתמש הראשון מהם במקרה הזה), נוכל להריץ את השאילתה הבאה:
SELECT * FROM SalesLT.Address as a WHERE a.AddressID in ( SELECT MIN(b.AddressID) FROM SalesLT.Address b GROUP BY City )
במקרה זה השתמשנו בפונקציית האגרגציה MIN כך שנקבל באמת את המשתמש הראשון מכל עיר ונשמיט את היתר.
יכולנו להשיג את אותו הדבר גם על ידי שימוש ב-JOIN למשל:
SELECT * FROM SalesLT.Address a2 WHERE a2.AddressID in ( SELECT MIN(a.AddressID) FROM SalesLT.Address a INNER JOIN SalesLT.Address as b ON a.AddressLine1 = b.AddressLine1 GROUP BY a.City )
GROUP BY HAVING
על מנת להכניס תנאי לפעולת הקיבוץ, נוכל להשתמש ב-HAVING.
שימו לב שלמרבית מהרשומות שבטבלה שלמעלה יש ערך NULL בעמודה AdressLine2.
נניח ונרצה לקבל את אותה התוצאה ללא רשומות כאלה, נוכל להשתמש ב-HAVING כך:
SELECT * FROM SalesLT.Address as a WHERE a.AddressID in ( SELECT MIN(b.AddressID) FROM SalesLT.Address b GROUP BY City HAVING a.AddressLine2 is not NULL )
*שימו לב שלמרות שנראה ש-HAVING פועל באופן זהה ל-WHERE יש ביניהם הבדלים:
SQL WHERE vs HAVING
לקריאה מורחבת על GROUP BY באתר של מייקרוסופט יש ללחוץ כאן.