-
אני ינסה לענות מה שנראה לי אני לא כל כך מבין בזה,(אל תסמוך עליי להלכה.) אבל לפחות יהיה לך עוד כיוון חשיבה.
כשאתה מדפיס את התוצאה של השאילתה הוא מדפיס לפי הערך monthYear ומציג ערך אחד בלבד ששווה ל 01-2022 למשל יציג לך רק את ראובן ב 01-2022 כי הוא כבר הדפיס משהו מ 01-2022.
ולכן לדוגמא אם תמחוק את ההכנסה של הנתונים של ראובן של 01-2022 ותדפיס תראה שפתאום את שמעון הוא גם מדפיס. (את 01-2022)
כלומר כשאתה ממין לפי הערך הזה הוא ידפיס רק אחד מכל ערך.
לסיכום, נראה ש GROUP BY monthYear
מכניס לקבוצה רק ערך אחד מכל סוג ולא את הכל. -
התחביר הנכון הוא כך:
SELECT monthYear, SUM(CASE WHEN name = 'REOUVEN' THEN price END) AS REOUVEN, SUM(CASE WHEN name = 'SHIMON' THEN price END) AS SHIMON, SUM(CASE WHEN name = 'LEVI' THEN price END) AS LEVI FROM AZMANOT GROUP BY monthYear ORDER BY monthYear DESC;
-
@OdedDvir יישר כוח. לא ידעתי שיש חילוק בין IF וCASE.
העברתי לMYSQL 8 וזה גם עובד נהדר, כנראה שיש הבדל מהותי יותר עם CASE שתופס על GROUP.
https://www.db-fiddle.com/f/75xSbAmhsC5wbDhfxTDxcR/1עכשיו לשאלה השניה.
מה הצורה הנכונה להכין שאילתא אוטומטית, שגם אם יהיו עשר לקוחות, זה יכין את הטבלא הזו בצורה נכונה.
תודה רבה! -
הנה דוגמה מצויינת למה היכולת של MYSQL להשמיט פונקציית צבירה בפירוש מביא לבאגים (https://tchumim.com/topic/13246, ואם להיות ספציפי למי שנראה לי מעניין אותו זה @יוסף-בן-שמעון).
@שואף, התיקון לבעיה שלך איננו ההבדל בין IF לבין CASE (אין לי מושג למה @OdedDvir על הדרך שיפר את זה עבור MSSQL).
הנקודה היא שלא עטפת את הIF בSUM.
ובשביל להבין מה הבעיה צריך פשוט להוריד את הGROUP BY ואז הבעיה בולטת לעיניים:
יש לנו שורה לכל קניה, ובשורה הראשונה הקניה היא של REUVEN ולכן הסכום שמה בREUVEN יהיה סכום הקניה, אולם העמודות של שמעון ולוי יהיו 1. מה קורה בעת הקיבוץ? כל שלושת השורות של חודש מסויים הופכים לשורה אחת. ואיזה ערך יופיע בכל אחד מהעמודות? אז איפה שצויין SUM, יופיע סיכום. איפה שלא, יילקח הערך של השורה הראשונה של הקבוצה... קרי השורה של REUVEN. -
@שואף אתה בעצם מבקש ליצור טבלת ציר. לא ידוע לי שיש פונקציית
PIVOT
ב-MySQL, לכן צריך להתחכם ולשרשר כמה משפטיCASE
ברצף.
כדי לקבל את שם העמודה בכל פעם, יש ליצור את נוסח המשפט באופן דינמי עבור כל ערך, ואז להשתמש בGROUP_CONCAT
:SET @sql = NULL; SELECT GROUP_CONCAT(DISTINCT CONCAT( 'SUM(CASE WHEN name = "', name, '" THEN price ELSE 0 END) AS ', name) ) INTO @sql FROM AZMANOT; SET @sql = CONCAT('SELECT monthYear, ', @sql, ' FROM AZMANOT GROUP BY monthYear'); SELECT @sql; PREPARE t FROM @sql; EXECUTE t; DEALLOCATE PREPARE t;
-
@dovid אמר במסד נתונים כטבלא בשני ממדים:
אין לי מושג למה @OdedDvir על הדרך שיפר את זה עבור MSSQL
צודק, בראש הקודח שלי תקוע ש-CASE עדיף מ-IF, (אאל"ט בגלל שהוא תומך ב Short-Circuting), אבל כאן זה לכאורה לא משנה, ואפשר לכתוב גם כך:
SUM(IF(name = 'REOUVEN', price, 0)) AS REOUVEN, ...
-
@OdedDvir תודה רבה מאוד! ישבתי ללמוד את השאילתא שלך, יש בה כמה אלמנטים שלא הכרתי.
תרשה לי לשאול כמה שאלות.
א. למה השורה הראשונה? ענין של תקינות?SET @sql = NULL;
ב. למה כתבת בשורה הרביעית ELSE 0 ? מה היה חסר בלי זה?
ג. שורה 11 כתבת SELECT @sql; כנ"ל זה היה נחוץ, או רק בשביל הדיבגינג?
שוב תודה.
-
@שואף למרות שהקוד לכאורה יעבוד גם בלי התוספות האלו, כתבתי שלענ"ד זה עניין של הרגלים טובים. הללו נועדו כדי למנוע בעיות בעתיד, כשכבר הספקת לשכוח פעמיים מה כתבת כאן בקוד, ואתה מוצא את עצמך מחפש בנרות את הבעיה.
זה הדברים הקטנים האלו בתכנות שעלולים לגרום בעיות גדולות בהמשך.
דוגמא משעשעת לכך היא הטעות שהשתרבבה לגוגל באחד העדכונים ל ChromeOS, וגרמה לאלפי משתמשים להנעל מחוץ לחשבון שלהם.
הטעות היתה בהשמטת תו אחד בודד בבדיקה של סיסמת המשתמש בתנאיif
, בו בטעות השתמשו באופרטור הבינארי&
במקום באופרטור הלוגי&&
.
דהיינו כתבו:if (key_data_.has_value() & !key_data_->label().empty()) {
במקום
if (key_data_.has_value() && !key_data_->label().empty()) {
מה שגרם להחזרה של ערך
false
גם במקרה של סיסמה נכונה, ולהציג למשתמש את ההודעה ש"אנו מצטערים, אבל לא הצלחנו לאמת את סיסמתך." -
@אפר-שריפה אמר במסד נתונים כטבלא בשני ממדים:
@שואף נראה לי שזה הרבה יותר רלוונטי אליך
https://stackoverflow.com/questions/15931607/convert-rows-to-columns-using-pivot-in-sql-serverאולי התכוונת לזה - https://stackoverflow.com/questions/7674786/how-can-i-return-pivot-table-output-in-mysql
יש שם כמה פתרונות...
-
D dovid העביר נושא זה מ-תכנות ב-