הבלוג של גרי רשף

26/10/2011

חישוב שינויים וסיכומים בעזרת פונקציות החלון החדשות של SQL Server 2012 Denali

שייך לקטגוריה: Uncategorized — גרי רשף @ 13:18

מד"ד התלוצץ פעם במידה רבה של צדק שבעזרת הפונקציות החדשות של גרסת Denali כל אחד יוכל להיות אב"ג, ובפוסט הזה אראה כיצד ניתן לחשב כעת בקלות הפרשים (מוחלטים ויחסיים) בסדרות תקופתיות, וכיצד ניתן מנגד לסכום את ההפרשים במקרה הצורך ולקבל את הסכומים התקופתיים.
לא אראה – לצורך ההשוואה – כיצד זה נעשה בעבר, ואציין רק שזה "קצת" מסובך ו"קצת" כבד; אלא אם כן מד"ד מארגן לי את ה-FastTrack שהגיעה לאחרונה לארץ + צוות חילוץ של פיקוד העורף.

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

Use tempdb;
Go

If Object_Id('T_Toshavim','U') Is Not Null Drop Table T_Toshavim;
Go

Create table T_Toshavim(Shana SmallInt Primary Key,
                        Toshavim Decimal(5,1),
                        Shinuy Decimal(5,1));
Go

Insert
Into T_Toshavim(Shana,Toshavim,Shinuy)
Values  (1948,872.7,NULL),
        (1949,1173.9,301.2),
        (1950,1370.1,196.2),
        (1951,1577.8,207.7),
        (1952,1629.5,51.7),
        (1953,1669.4,39.9),
        (1954,1717.8,48.4),
        (1955,1789.1,71.3),
        (1956,1872.4,83.3),
        (1957,1976.0,103.6),
        (1958,2031.7,55.7),
        (1959,2088.7,57.0),
        (1960,2150.4,61.7),
        (1961,2234.2,83.8),
        (1962,2331.8,97.6),
        (1963,2430.1,98.3),
        (1964,2525.6,95.5),
        (1965,2598.4,72.8),
        (1966,2657.4,59.0),
        (1967,2776.3,118.9),
        (1968,2841.1,64.8),
        (1969,2929.5,88.4),
        (1970,3022.1,92.6),
        (1971,3120.7,98.6),
        (1972,3225.0,104.3),
        (1973,3338.2,113.2),
        (1974,3421.6,83.4),
        (1975,3493.2,71.6),
        (1976,3575.4,82.2),
        (1977,3653.2,77.8),
        (1978,3737.6,84.4),
        (1979,3836.2,98.6),
        (1980,3921.7,85.5),
        (1981,3977.7,56.0),
        (1982,4063.6,85.9),
        (1983,4148.5,84.9),
        (1984,4199.7,51.2),
        (1985,4266.2,66.5),
        (1986,4331.3,65.1),
        (1987,4406.5,75.2),
        (1988,4476.8,70.3),
        (1989,4559.6,82.8),
        (1990,4821.7,262.1),
        (1991,5058.8,237.1),
        (1992,5195.9,137.1),
        (1993,5327.6,131.7),
        (1994,5471.5,143.9),
        (1995,5612.3,140.8),
        (1996,5757.9,145.6),
        (1997,5900.0,142.1),
        (1998,6041.4,141.4),
        (1999,6209.1,167.7),
        (2000,6369.3,160.2),
        (2001,6508.8,139.5),
        (2002,6631.1,122.3),
        (2003,6748.4,117.3),
        (2004,6869.5,121.1),
        (2005,6990.7,121.2),
        (2006,7116.7,126.0),
        (2007,7243.6,126.9),
        (2008,7419.1,175.5),
        (2009,7552.0,132.9),
        (2010,7695.1,143.1);
Go

Select  *
From    T_Toshavim
Order By Shana;
Go

clip_image002

כפי שאפשר לראות- בטבלה יש יתירות, ומופיעים שם גם מספר התושבים בכל שנה וגם השינוי השנתי.

אנחנו נניח בשלב הראשון שרק מספר התושבים מופיע ושיש לחשב את השינוי השנתי,

ובשלב השני נניח שמופיעים השינויים וצריך לסכום אותם ולחבר למספר התושבים ההתחלתי כדי לדעת את מספרם בכל שנה:

Select  *,
        Toshavim-Lag(Toshavim,1) Over(Order By Shana) Shinuy1
From    T_Toshavim
Order By Shana;

clip_image004

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

סכימת השינויים:

Select  *,
        First_Value(Toshavim) Over(Order By Shana)+
        Sum(Shinuy) Over(Order By Shana Rows Between Unbounded Preceding And Current Row) Toshavim1
From T_Toshavim
Order By Shana;

clip_image006

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

ולפונקציית החלון Sum התווסף האופרטור Rows שמאפשר להגדיר מסגרת דינאמית (Frame) שאותו יש לסכום.

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

If Object_Id('T_Madad','U') Is Not Null Drop Table T_Madad;
Go

Create Table T_Madad(Shana SmallInt,
                    Hodesh TinyInt,
                    Madad Decimal(10,7),
                    Shinuy Decimal(19,18),
                    Constraint PK_T_Madad Primary Key Clustered(Shana, Hodesh));
Go

Insert
Into    T_Madad
Values  (2010, 12, 101.7907634, 0.003717471847701109),
        (2010, 11, 101.4137606, 0.000930232490198810),
        (2010, 10, 101.3195099,0.002798507257722001 ),
        (2010, 9, 101.0367578, 0.002806360879009696),
        (2010, 8, 100.7540057, 0.004699248775403322),
        (2010, 7, 100.2827521, 0.004721434971020463),
        (2010, 6, 99.8114986, 0.002840908882540784),
        (2010, 5, 99.5287465, 0.003802282101270077),
        (2010, 4, 99.1517436, 0.008628954305672938),
        (2010, 3, 98.3034873, 0.000959692827914721),
        (2010, 2, 98.2092366, -0.002870813187265860),
        (2010, 1, 98.4919887, Null);
Go

Select  *
From    T_Madad
Order By Shana,
        Hodesh;
Go

clip_image008

בשלב ראשון נחשב על פי המדד החודשי את השינוי ברמת המחירים בכל חודש, כשהפעם החישוב הוא יחסי; כלומר- לא בכמה נקודות עלה המדד (מספר מופשט שאין לו משמעות) אלא בכמה אחוזים:

Select  *,
        Madad/Lag(Madad,1) Over(Order By Shana,Hodesh)-1 Shinuy1
From    T_Madad
Order By Shana,
        Hodesh;

clip_image010

חילקנו את המדד הנוכחי בקודם לו והחסרנו 1.

האתגר הגדול הוא לסכום את השינויים במדד, מכיוון שמדובר במכפלה ולא בסכום, ולכך אין פונקצייה אגרגטיבית מתאימה כדוגמת Sum. הפתרון שלמדתי עליו מאב"ג הוא להשתמש בלוגריתמים: מכפלה של מספרים שוות ערך לסכום של הלוגריתמים שלהם (סכום שעליו מופעל אנטי-לוג). משהו שלומדים לבגרות:

Select  *,
        First_Value(Madad) Over(Order By Shana,Hodesh)*Exp(Sum(Log(1+IsNull(Shinuy,0)))
                                                                Over(Order By Shana,Hodesh
                                                                Rows Between Unbounded Preceding And Current Row)) Madad1
From    T_Madad
Order By Shana,
        Hodesh;

clip_image012

המדד הראשון (98.4919887) המתקבל על ידי First_Value

מוכפל במכפלה של השינויים במדד (ליתר דיוק: השינוי במדד + 1) המתקבלת מהפעלה של פונקציית Log (לפי הבסיס הטבעי) עליה, סכימה מצטברת שלהם על ידי Sum, וביצוע אנטי-לוג בעזרת הפונקציה Exp המחזירה ex כאשר X הוא הפרמטר (סכום הלוגריתמים) המועבר לפונקציה.

5 תגובות »

  1. [...] ומחשבים את המכפלה שלהם בעזרת לוגריתמים (כתבתי על זה כאן בחצי השני המתייחס למדד המחירים [...]

    פינגבאק מאת ישום היררכיה (עץ) בעזרת מספרים ראשוניים « הבלוג של גרי רשף — 17/01/2012 @ 21:05

  2. [...] שורש ריבועי. אם נפעיל את החישוב על טבלת תושבי המדינה מהפוסט לפני הקודם, [...]

    פינגבאק מאת מקדם המתאם - גרי רשף — 01/11/2011 @ 19:15

  3. [...] שורש ריבועי. אם נפעיל את החישוב על טבלת תושבי המדינה מהפוסט לפני הקודם, [...]

    פינגבאק מאת מקדם המתאם « הבלוג של גרי רשף — 01/11/2011 @ 19:12

  4. [...] בפוסט הקודם יצרנו טבלת תושבים של מדינת ישראל לפי שנים, וכעת נעשה בה שימוש כדי לחזות את מספר תושבי המדינה בשנת 2030. T – הגדרנו מיהו X ומיהו Y. T1- חישבנו את הערכים השונים עבור הנוסחה. T2- חישוב a. T3- חישוב b, ולסיום- חישוב התחזית (כלומר- להציב במשוואה Y=aX+b את ערכי a,b המחושבים ואת X=2030 ולחשב את Y): [...]

    פינגבאק מאת רגרסיה לינארית – שיטת הריבועים הפחותים - גרי רשף — 31/10/2011 @ 21:48

  5. [...] בפוסט הקודם יצרנו טבלת תושבים של מדינת ישראל לפי שנים, וכעת נעשה בה שימוש כדי לחזות את מספר תושבי המדינה בשנת 2030. T – הגדרנו מיהו X ומיהו Y. T1- חישבנו את הערכים השונים עבור הנוסחה. T2- חישוב a. T3- חישוב b, ולסיום- חישוב התחזית (כלומר- להציב במשוואה Y=aX+b את ערכי a,b המחושבים ואת X=2030 ולחשב את Y): [...]

    פינגבאק מאת רגרסיה לינארית – שיטת הריבועים הפחותים « הבלוג של גרי רשף — 31/10/2011 @ 21:33


RSS של התגובות לרשומה הזאת טרקבאק קישור

להגיב

Fill in your details below or click an icon to log in:

WordPress.com Logo

אתה מגיב באמצעות חשבון WordPress.com שלך. Log Out / לשמור )

Twitter picture

אתה מגיב באמצעות חשבון Twitter שלך. Log Out / לשמור )

Facebook photo

אתה מגיב באמצעות חשבון Facebook שלך. Log Out / לשמור )

Connecting to %s

ערכת עיצוב: Shocking Blue Green. בלוג בוורדפרס.קום.

Follow

Get every new post delivered to your Inbox.