none
שאילתא משתי טבלאות RRS feed

  • שאלה

  • יש לי טבלת לקוחות המקושרת  (באמצעות מספר לקוח) לשתי טבלאות טבלת מסמכי חיוב וטבלת מסמכי זיכוי,

    איך אני מקבל רשימת כל המסמכים ללקוח  מבלי להשתמש בפקודת UNION ?

    אני לא מקבל תובות כי זה לא אפשרי או שהשאלה טפשית?
    • נערך על-ידי yalin9 יום שלישי 22 אוקטובר 2013 10:16
    יום שלישי 22 אוקטובר 2013 08:51

תשובות

  • קודם כל אני שמח לשמוע שכבר הצלחנו להועיל במשהו :-)

    א ני רוצה לתת הקדמה קטנה לצרכי לימוד ואז אשים פתרון לשאלה שלך:

    1. אתה מדבר על טבלאות מקושרות אבל ה DDL שלך לא מראה שום קשרים בין הטבלאות. יותר מכך אין לך אינדקסים וכל הטבלאות בנויות בצורה של HASH (טבלאות ללא סדר וארגון).

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

    כרגע אתה מוציא נתונים של משתמש מסויים. האם זה מה שאתה צריך? ז"א אתה בטוח שאתה רוצה את התוצאה של כל הנתונים מטבלת invoices + כל הנתונים מטבלת creditNotes בלי קשר בינהן (אם כן זה בדיוק המטרה של UNION).

    3. מה ההתנגדות שלך לשימוש ב UNION אם הוא מתאים?!? אם השאילתה שאתה מחפש היא מה שרשמת אז השימוש ב UNION נכון ובמקום. למה לחפש בכוח דרך אחרת? זה כמו מישהו שרוצה לנסוע מתל אביב לירושליים אבל הוא שואל אם אפשר לנסוע דרך אילת. התשובה כן זה אפשרי אבל למה?!?

    גם כאן אם רוצים בכוח לא לעבוד עם UNION אז אין בעיה, אבל למה?

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

    אחרי כל הבלבלת והמילים הגיע הזמן לפתרון:-)
    אז כיצד מבצעים UNION ללא UNION?
    פשוט: מבצעים FULL OUTER JOIN עם חיבור נתונים לפי 1=0.

    הסבר: FULL OUTER JOIN מחזיר לכל נתון בטבלה ראשונה נתון מתאים בטבלה שנייה. אבל מכיוון שבחרנו התאמה של 1=0 אז לעולם לא יהיה נתון מתאים ולכן מטבלה שנייה יחזרו NULL תמיד. כמו כן FULL OUTER JOIN מחזיר את כל הרשומות מטבלה שנייה עם התאמה לרשומות מטבלה ראשונה. שוב בגלל התנאי שלנו 1=0 נקבל הפעם את כל הרשומות מטבלה שנייה ו NULL במקום הנתונים מטבלה ראשונה.

    לשם ההבנה נסה להריץ את השאילתה הבאה:

    select *
    from invoices I
    FULL OUTER JOIN creditNotes C ON 1=0
    where I.custId = 1234 or C.custId = 1234
    עתה נעזר בפונקציה COALESCE על מנת לקבל בכל רשומה רק את הנתון שהוא לא NULL ולכן כך תיראה השאילתה הסופית בפועל:
    select 
    	COALESCE(I.custId, C.custId)
    	,COALESCE(I.docNo, C.docNo)
    	,COALESCE(I.docSum, C.docSum)
    from invoices I
    FULL OUTER JOIN creditNotes C ON 1=0
    where I.custId = 1234 or C.custId = 1234

    בסינון בסוף אנחנו בוחרים OR מכיוון שבנתונים יש או רק נתון של custId מטבלה ראשונה (ו NULL בחלק של השני) או נתון מטבלה שנייה (ו NULL בחלק הראשון).

    מקווה שזה עוזר :-)


    [Personal Site] [Blog] [Facebook]signature

    • נערך על-ידי pituachMVP, Editor יום שלישי 22 אוקטובר 2013 18:01
    • סומן כתשובה על-ידי yalin9 יום רביעי 23 אוקטובר 2013 06:29
    יום שלישי 22 אוקטובר 2013 17:21
    מנחה דיון

כל התגובות

  • אתה צריך להשתמש ב JOIN (הנושא לא כל כך קשור ל UNION)

    תבדוק את המדריך הבא אם הוא עוזר לך להבין מה אתה צריך (מומלץ לקרוא וללמוד את כולו מההתחלה ועד הסוף)

    http://www.w3schools.com/sql/sql_join.asp


    [Personal Site] [Blog] [Facebook]signature

    יום שלישי 22 אוקטובר 2013 11:17
    מנחה דיון
  • אם כוונתך לשאילתא הבאה:

    נניח שטבלת customers מכילה עמודה אחת של custID

    וטבלאות invoices ו credits מכילות שתיהן שלש עמודות custID,docNo,docSum

    SELECT customers.CustId,invoices.DocNo,invoices.docSum

    ,credits.DocNo,credits.docSum FROM customers LEFT JOIN invoices on customers.custId=invoices.custId LEFT JOIN credits on customers.custId=credits.custId

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

    הפתרון שאני מכיר הוא:

    SELECT custId,docNo,docSum
    FROM invoices
    UNION 
    SELECT custId,docNo,docSum
    FROM credits
    ושוב אני לא יכול להשתמש בפקודת UNION

    איציק

    יום שלישי 22 אוקטובר 2013 13:23
  • היי

    אני לא בטוח שאני הבנתי מה אתה צריך לקבל בסיום, אם תצרף לנו DDL+DML אז נוכל להבין מה קורה tmkl' ומה צריך לקרות' ומה לא קורה :-)

    בכלל צריך לדעת שבלי לצרף DD+DML אנחנו סתם נבזבז זמן בניחושים.

    אנא צרף:

    1. DDL

    2. DML

    3. רשימה של התוצאות שאתה רוצה לקבל בסיום לפי ה DDL+DML שלך

    * ועכשיו לשאלה הגדולה שבטח אתה זואל. מה זה לעזזל DDL או DML ומה אני מבלבל את השכל :-)

    אז הנה הסבר בקישור הבא ובכל שאלה בעתיד אנא הקפד לצרף... כן... DDL+DML כדי שיוכלו לעזור לך בצורה יותר טובה

    http://ariely.info/Blog/tabid/83/EntryId/70/Data-Definition-Language-DDL-and-Data-Manipulation-Language-DML.aspx


    [Personal Site] [Blog] [Facebook]signature

    יום שלישי 22 אוקטובר 2013 14:01
    מנחה דיון
  • רונן,

    מצ"ב DML (למדתי משהו היום)

    האם אפשר להגיע לתוצאה המוצגת ללא פקודת UNION ?

    CREATE TABLE customers (custId int)
    INSERT customers (custId) VALUES (1234)
    CREATE TABLE invoices (custId int,docNo int,docSum smallmoney)
    INSERT INTO invoices VALUES (1234,1,1000),(1234,2,987)
    CREATE TABLE creditNotes (custId int,docNo int,docSum smallmoney)
    INSERT INTO creditNotes VALUES (1234,10,456),(1234,11,256)
    SELECT custId ,docNo ,docSum
    FROM invoices
    WHERE custId=1234
    UNION
    SELECT custId ,docNo ,docSum
    FROM creditNotes
    WHERE custId=1234
    --RESULT:
    1234	1	1000
    1234	2	987
    1234	10	456
    1234	11	256


    איציק

    יום שלישי 22 אוקטובר 2013 14:32
  • קודם כל אני שמח לשמוע שכבר הצלחנו להועיל במשהו :-)

    א ני רוצה לתת הקדמה קטנה לצרכי לימוד ואז אשים פתרון לשאלה שלך:

    1. אתה מדבר על טבלאות מקושרות אבל ה DDL שלך לא מראה שום קשרים בין הטבלאות. יותר מכך אין לך אינדקסים וכל הטבלאות בנויות בצורה של HASH (טבלאות ללא סדר וארגון).

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

    כרגע אתה מוציא נתונים של משתמש מסויים. האם זה מה שאתה צריך? ז"א אתה בטוח שאתה רוצה את התוצאה של כל הנתונים מטבלת invoices + כל הנתונים מטבלת creditNotes בלי קשר בינהן (אם כן זה בדיוק המטרה של UNION).

    3. מה ההתנגדות שלך לשימוש ב UNION אם הוא מתאים?!? אם השאילתה שאתה מחפש היא מה שרשמת אז השימוש ב UNION נכון ובמקום. למה לחפש בכוח דרך אחרת? זה כמו מישהו שרוצה לנסוע מתל אביב לירושליים אבל הוא שואל אם אפשר לנסוע דרך אילת. התשובה כן זה אפשרי אבל למה?!?

    גם כאן אם רוצים בכוח לא לעבוד עם UNION אז אין בעיה, אבל למה?

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

    אחרי כל הבלבלת והמילים הגיע הזמן לפתרון:-)
    אז כיצד מבצעים UNION ללא UNION?
    פשוט: מבצעים FULL OUTER JOIN עם חיבור נתונים לפי 1=0.

    הסבר: FULL OUTER JOIN מחזיר לכל נתון בטבלה ראשונה נתון מתאים בטבלה שנייה. אבל מכיוון שבחרנו התאמה של 1=0 אז לעולם לא יהיה נתון מתאים ולכן מטבלה שנייה יחזרו NULL תמיד. כמו כן FULL OUTER JOIN מחזיר את כל הרשומות מטבלה שנייה עם התאמה לרשומות מטבלה ראשונה. שוב בגלל התנאי שלנו 1=0 נקבל הפעם את כל הרשומות מטבלה שנייה ו NULL במקום הנתונים מטבלה ראשונה.

    לשם ההבנה נסה להריץ את השאילתה הבאה:

    select *
    from invoices I
    FULL OUTER JOIN creditNotes C ON 1=0
    where I.custId = 1234 or C.custId = 1234
    עתה נעזר בפונקציה COALESCE על מנת לקבל בכל רשומה רק את הנתון שהוא לא NULL ולכן כך תיראה השאילתה הסופית בפועל:
    select 
    	COALESCE(I.custId, C.custId)
    	,COALESCE(I.docNo, C.docNo)
    	,COALESCE(I.docSum, C.docSum)
    from invoices I
    FULL OUTER JOIN creditNotes C ON 1=0
    where I.custId = 1234 or C.custId = 1234

    בסינון בסוף אנחנו בוחרים OR מכיוון שבנתונים יש או רק נתון של custId מטבלה ראשונה (ו NULL בחלק של השני) או נתון מטבלה שנייה (ו NULL בחלק הראשון).

    מקווה שזה עוזר :-)


    [Personal Site] [Blog] [Facebook]signature

    • נערך על-ידי pituachMVP, Editor יום שלישי 22 אוקטובר 2013 18:01
    • סומן כתשובה על-ידי yalin9 יום רביעי 23 אוקטובר 2013 06:29
    יום שלישי 22 אוקטובר 2013 17:21
    מנחה דיון
  • כמובן שצריך להזכיר ששימוש בדרכים עקיפות כאלה נועדו רק לצרכי הלימוד ובפועל השאילתה מעל מאוד לא יעילה. במסגרת המשחקים כמובן שאפשר להצי דרכים נוספות. דרך נוספת ויעילה יותרלמשל היא פשוט ליצור טבלה זמנית ולהכניס אליה את כל התוצאות של שאילתה 1 + שאילתה 2 ואז לבצע שאילתת SELECT מהטבלה הזמנית. שוב בפתרון זה לא השתמשנו ב UNION במפורש אבל למעשה ביצענו את הפעולה של UNION ולכן בחרתי להציג קודם את השיטה בעזרת JOIN... אחרי הכל שאלה זו אינה במטרה להגיע לדרך מיטבית אלא פשוט להציג רעיון :-)

    [Personal Site] [Blog] [Facebook]signature

    יום שלישי 22 אוקטובר 2013 20:33
    מנחה דיון
  • אכן נפתרה הבעיה.

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

    תודה על העזרה


    איציק

    יום רביעי 23 אוקטובר 2013 06:29
  • בכיף איציק, אבל אני חושב שאתה טועה בגישה

    זו דרך לא יעילה ולא מומלצת ואין הגיון לא לעבוד עם UNION בגלל מגבלה בתכנון האפליקציה. צריך להבין מה הבעיה בתכנון של האפליקציה שלך ומדוע קורה מה שקורה.

    * הדרך הכי קלה לעקוף את הבעיה שאתה מציג היא להשתמש בפרוצדורה שמורה SP שמקבל נתון של מספר ה ID ומחזירה את הנתונים בעזרת שאילתת UNION.

    אני ממליץ לקחת צעד אחד אחורה ולהשקיע עוד זמן בתכנון לפני שניגשים לכתיבת הקוד :-)

    בהצלחה בכל דרך שתבחר,


    [Personal Site] [Blog] [Facebook]signature

    יום רביעי 23 אוקטובר 2013 06:40
    מנחה דיון