טיפ קצר: למה כשעושים Average על עמודה ב DB מקבלים ממוצע שלם, גם כשהתוצאה אמורה להיות עשרונית?

9 בNovember 2009

3 תגובות

נניח שיש לכם טבלה, עם עמודה הכוללת מספרים שלמים (int).באפליקציה שלכם, שלצורך העניין, משתמשת נניח ב LINQ to SQL או ADO.NET Entity Framework, אתם רוצים לקבל את הממוצע של העמודה הזאת. אתם אומרים לעצמכם שזה לא אמור להיות מורכב בכלל. יש Extension Method לאגרגרציה של נתונים, אחת מהם היא Average.
אתם כותבים אפליקציה פשוטה שמריצה אותה ואמורה לעשות את הממוצע של המספרים 1,1,2. התוצאה המצופה היא אחד ושליש. אתם מקבלים אחד. למה?

ההסבר פשוט מאד: משפט ה SQL שנוצר כתוצאה משימוש ב Average משתמש בפונקציית T-SQL בשם AVG. מישהו במיקרוסופט החליט, שכשמפעילים AVG על עמודה שה type שלה הוא int, אז הערך המוחזר יהיה גם הוא int. החלטה מעניינת, בהתחשב בעובדה שזה אומר שבמספר די רחב של מקרים Average לא תחזיר את הממוצע – אבל אני לא מתיימר להבין את (חוסר) ההיגיון מאחורי זה.

לכן, אפילו אם הערך שאתם רוצים לאכסן בעמודה הוא מספר שלם בהכרח, אבל רוצים לקבל את הממוצע האמיתי – כדאי שתגדירו את העמודה ל real.

בהצלחה.

הוסף תגובה
facebook linkedin twitter email

Leave a Reply

Your email address will not be published. Required fields are marked *

3 תגובות

  1. משה2 בDecember 2009 ב 18:29

    לא הייתי רץ לעשותאת השינוי הזה בלי להבין עד הסוף את הנזק שהוא גורם לביצועים במערכות גדולות.

    Reply
  2. יעקב4 בMay 2010 ב 12:57

    יש – כמו שאומרים – הגיון בשגעון. ואם תסתכל ב-bol של SQL תראה שיש כללי המרה ב-SQL ומה שצריך לעדות זה פשוט
    select AVG(cast(1 as numeric(9,2)) וזה יפתור את הבעיה.

    נ.ב. בשום אופן לא להמיר ל-real כי יוצא מספר לא מדוייק בעליל, אלא להמיר ל-numeric

    Reply
  3. דוד11 בJuly 2012 ב 10:19

    למה real פחות טוב מ-numeric?

    Reply