לדלג לתוכן

Window Functions ב-SQL מוסבר

יש רגע מוכר לכל מי שלומד SQL - אתם יודעים לכתוב SELECT, WHERE, ואפילו GROUP BY, אבל אז מבקשים מכם "תראו לי את הדירוג של כל עובד בתוך המחלקה שלו" או "תחשבו סכום מצטבר של מכירות לפי חודש", ופתאום שום דבר שלמדתם לא מספיק. שם בדיוק נכנסות window functions, ולמרות שהן נשמעות מפחיד, הרעיון שמאחוריהן פשוט מאוד.

הבעיה ש-GROUP BY לא פותר

GROUP BY מצוין לחישוב סיכומים - כמה הזמנות היו לכל לקוח, מה הממוצע לכל מחלקה. אבל יש לו מגבלה מהותית - הוא מאחד שורות. אם יש לכם עשר הזמנות ואתם עושים GROUP BY לפי לקוח, אתם מקבלים בחזרה שורה אחת לכל לקוח, לא עשר. מה קורה כשאתם רוצים לדעת גם את הדירוג של כל הזמנה בודדת ביחס לשאר, אבל עדיין לראות את כל עשר השורות בנפרד, לא מאוחדות? GROUP BY פשוט לא בנוי לזה.

איך Window Functions פותרות את זה

Window function מבצעת חישוב על קבוצה של שורות - שנקראת "window", חלון - אבל בלי לאחד אותן לשורה אחת. כל שורה מקבלת בחזרה ערך מחושב לצידה, בעודה נשארת שורה עצמאית משלה. זה ההבדל המהותי - הפלט נשאר באותה כמות שורות שנכנסה, פשוט עם עמודה נוספת שמכילה את התוצאה של החישוב.

הפקודה שמייצרת חלון היא OVER(), לרוב בשילוב עם PARTITION BY שמגדיר איך לחלק את השורות לקבוצות. לדוגמה, RANK() OVER (PARTITION BY department ORDER BY salary DESC) נותן לכל עובד דירוג לפי שכר, אבל הדירוג מתאפס בכל מחלקה בנפרד, כי PARTITION BY department אומר "תתייחס לכל מחלקה כחלון נפרד".

הפונקציות הכי שימושיות

ROW_NUMBER() נותנת מספר סידורי לכל שורה בתוך הקבוצה שלה - שימושי לדוגמה כדי למצוא את ההזמנה האחרונה של כל לקוח. RANK() ו-DENSE_RANK() דומים אבל מתמודדים אחרת עם תיקו - RANK מדלג על מספרים אחרי תיקו, DENSE_RANK לא. SUM() OVER() ו-AVG() OVER() מאפשרים לחשב סכום מצטבר או ממוצע נע - למשל, סכום המכירות המצטבר מתחילת השנה עד כל חודש, שורה אחר שורה. LAG() ו-LEAD() מאפשרות לראות את הערך של השורה הקודמת או הבאה - שימושי מאוד כדי לחשב שינוי באחוזים בין חודש לחודש.

דוגמה שמראה את הכוח האמיתי

תארו לעצמכם טבלת מכירות חודשיות ואתם רוצים לדעת, לכל חודש, מה הסכום המצטבר מתחילת השנה. בלי window functions, זה דורש subquery מסובך שמחשב סכום לכל שורה בנפרד - איטי ומסורבל. עם window function, זו שורה אחת: SUM(sales) OVER (ORDER BY month). זה בדיוק ההבדל בין שאילתת SQL שנראית כמו שרשור טלאים לבין שאילתה שכתובה כמו שמישהו שמבין את הכלי כתב אותה.

למה זה שווה להשקיע בלימוד שלהן

מפתחי backend רבים מסתדרים שנים בלי לגעת ב-window functions, כי אפשר לפתור כמעט כל בעיה עם קוד באפליקציה במקום ב-SQL. הבעיה היא שזה לרוב הרבה יותר איטי - למשוך את כל הנתונים לשרת האפליקציה ולחשב שם דירוג או סכום מצטבר בלולאה, במקום לתת למסד הנתונים, שבנוי בדיוק בשביל זה, לעשות את זה ביעילות. שליטה ב-window functions היא בדיוק סוג המיומנות שמבדילה מפתח שיודע לכתוב שאילתה שעובדת ממפתח שיודע לכתוב שאילתה שגם מהירה.

מאיפה מתחילים

להבין window functions דורש קודם בסיס טוב ב-SQL רגיל - SELECT, JOIN, GROUP BY - ורק אז הן הופכות להרחבה טבעית ולא לעוד תחביר מוזר לשינון. בקורס צד-שרת שלנו אנחנו עובדים עם מסדי נתונים אמיתיים לאורך הקורס, בונים שאילתות אמיתיות על נתונים אמיתיים, בעברית ובחינם.

תקועים על שאילתה מסובכת שלא מצליחה להסתדר? יש בקהילה שלנו אנשים ששמחים לעזור לפתור אותה יחד.

הצטרפו לקהילה בדיסקורד