קבלת נתוני 2 שנים

zag78

New member
קבלת נתוני 2 שנים

שלום רב!
אני מריץ על SQL SERVER את בסיס הנתונים לדוגמא של מיקרוסופט northind.
הכיוון שאליו אני חותר, הוא השוואת נתוני המכירות בין 2 שנים עוקבות.
הנתונים מתקבלים מ2 טבלאות: order details, orders. בorders יש את תאריך המכירה, ואילו בorder details יש את מחיר יחידה ואת כמותו.

בתור התחלה כתבתי שאילתה שמוצאת את נתוני המכירה עבור כל שנה, וזה עובד סבבה. להלן השאילתה:
select year(o_OrderDate) , sum(od.Quantity * od.UnitPrice)
from [Order Details] od ,Orders o
where od.OrderID = o_OrderID
group by year(o_OrderDate)
order by year(o_OrderDate)​

בשלב שני אני מנסה להכניס גם את נתוני השנה הקודמת.
בתור התחלה הכנסתי רק בתוך שורת הfrom את נתוני השנה הקודמת (מה שלכאורה לא אמור לשנות כלום, כי הרי לא משכתי מהם), וזה גורם להצגת מספרים שונים לגמרי. למה?
צירפתי את שלב 2 של השאילתה:
select year(o_OrderDate) , sum(od.Quantity * od.UnitPrice)
from [Order Details] od ,Orders o ,[Order Details] od2 , Orders o2
where od.OrderID = o_OrderID
group by year(o_OrderDate)
order by year(o_OrderDate)​
 

zag78

New member
רציתי להוסיף

כי גם כשאני מכניס תנאים, כך שo2,od2 ייצגו בהכרח את השנה הקודמת, זה עדיין נותן לי מספרים מופרכים.
select year(o_OrderDate) , sum(od.Quantity * od.UnitPrice)
from [Order Details] od ,Orders o ,[Order Details] od2 , Orders o2
where od.OrderID = o_OrderID and od2.OrderID = o2.OrderID and year(o_OrderDate) = year(o2.OrderDate)+1
group by year(o_OrderDate)
order by year(o_OrderDate)​
 

pitoach

New member
צהריים טובים,

האם אתה יודע לעבוד עם פעולות JOIN מפורשות במקום לרשום כמה טבלאות עם פסיק בינהן בחלק של הFROM?

אני חושב שאם תרשום את השילתה מעט שונה יהיה יותר קל לנתח אותה ולהגיע להבדלים. כרגע לא עברתי על השאילתה עדיין מכיוון שאין לי את מסד הנתונים הזה זמין, ואין לי זמן כרגע, אבל אני אנסה להגיע לזה המשך. בינתיים תענה בבקשה על השאלה, כדי שנדע לכוון את התשובה לידע שלך. אם אתה יודע לעבוד עם JOIN מפורש אז אנא נסה לנסח את אותן שאילתות תוך שימוש ב JOIN מפורש.

ניתן ללמוד על JOIN כאן (עדיף לעבור על כל המדריך אבל זה קישור ישיר לתחילת הפרק של JOIN):
http://www.w3schools.com/sql/sql_join.asp
 

zag78

New member
גם עם join זה בעייתי

צירפתי את הגירסה עם join
select year(o_OrderDate) , sum(od.Quantity * od.UnitPrice)
from [Order Details] od join Orders o on od.OrderID = o_OrderID
join Orders o2 on year(o_OrderDate) = year(o2.OrderDate)+1
join [Order Details] od2 on od2.OrderID = o2.OrderID
group by year(o_OrderDate)
order by year(o_OrderDate)​
 

pitoach

New member
הסבר

שבת שלום

1. Northwind הוא מסד נתונים מאוד ישן שאינו מתאים ללימוד האפשרויות החדשות שיש בגרסאות השרתים החדשות יותר. מאוד מומלץ להתרגל ללמוד תוך עבוה עם מסדי הנתונים הלימודיים החדשים יותר ממשפחת AdventureWorks.

2. לא אמרתי ששימוש ב JOIN אמור לעזור בביצועים כמובן. זה רק רישום יותר נקי ויותר קל לעבודה וניתוח שלנו. אתה צריך להתרגל תמיד לעבד בכתיבה כזו לדעתי ולהיפטר מהרגלים ישנים של רישום כמה טבלאות עם פסיק בינהם.

3. לגבי השאלה שלך:
"בתור התחלה הכנסתי רק בתוך שורת הfrom את נתוני השנה הקודמת (מה שלכאורה לא אמור לשנות כלום, כי הרי לא משכתי מהם), וזה גורם להצגת מספרים שונים לגמרי. למה?"

האמירה שלך "מה שלכאורה לא אמור לשנות כלום, כי הרי לא משכתי מהם" לא נכונה וזה מקור הבעיה. אתה מערבב בין הצגה של הנתונים בחלק של ה select לבין שימוש בנתונים במשך השאילתה


הדרך לחקור שאילתה ולהבין מה נעשה מאחורי הקלעים, היא להתחיל מבדיקה של תוכנית ההרצה. שרתי SQL SERVR בנהיגוד לשרתים אחרים לא באמת מריצים את השאילתה שאתה כותב אלא מעבירים אותה דרך מנוע מיטוב בשם sql server Query Optimizer engine. על מנת לראות מה המסקנות של השרת ומה הוא יבצע בפועל עלינו לחקור את תוכנית ההרצה שה optimaizer בנה עבור השאילתה שלך. שם תוכל לראות אם כן היה שימוש או לא היה שימוש בטבלה מסויימת.

בקישור הבא תוכל לקרוא מעט מאוד ובקצרה על התהליך מאחורי הקלעים
https://www.simple-talk.com/sql/sql-training/the-sql-server-query-optimizer/

דרך אגב בשאילתה שלך עשית פעמיים שימוש בטבלת Orders ופעמיים שימוש בטבלת [Order Details]. עתה אם תסכל בתמונה המצורפת להודעה, של תוכנית ההצה ותוכל לראות שאכן היה שימוש בכל ארבעת הטבלאות שלך.

 

eyalgorithm

New member
המספרים המופרכים נובעים ממכפלה קרטזית

הבעיה כאן היא אפיון לא נכון של השאילתה.
אם אני מבין נכון - אתה רוצה לקבל עבור כל שנה את סך המכירות באותה השנה, ולצידן את סך המכירות בשנה שקדמה לה.
בשביל זה אתה צריך קודם כל לאפיין את השלבים של השאילתה:
1. סך המכירות בכל שנה - עשית נכון.
2. להצליב את טבלת סך המכירות בשנה לעצמה בשביל לקבל את המכירות בשנה הקודמת, לצד המכירות בשנה הנוכחית.

מה שעשית בקוד הוא לעקוף את שלב סך המכירות בכל שנה, והצלבה של כל המכירות בשנה הקודמת עבור כל הזמנה בנפרד במקום לכלל ההזמנות (שים לב שה-group by שעשית מתייחס רק לשנה הנוכחית ולא לשנה הקודמת) - לכן המספרים שקיבלת הם סך המכירות בכל שנה כפול כמות ההזמנות בשנה הקודמת ('מכפלה קרטזית' של הרשומות).
נסה כך:
select current_year.yyyy, current_year.sales as cur_year_sales, prev_year.sales as prev_year_salesfrom
(
select year(o.orderdate) as yyyy, sum(od.Quantity*od.UnitPrice) as sales
from [dbo].[Orders] o join [dbo].[Order Details] od on o.orderid = od.OrderID group by year(o.orderdate) ) current_yearleft join ( select year(o.orderdate) as yyyy, sum(od.Quantity*od.UnitPrice) as sales from [dbo].[Orders] o join [dbo].[Order Details] od on o.orderid = od.OrderID group by year(o.orderdate) ) prev_yearon current_year.yyyy = prev_year.yyyy+1order by current_year.yyyy
 
למעלה