במאמר הקודם דיברנו על שליפת נתונים באמצעות SELECT מטבלת MySQL. במאמר הזה אנו נרחיב את שליפת הנתונים כאשר אנו בעצם שולפים מידע משתי טבלאות או יותר.
נשאלת השאלה, מדוע יש לשלוף נתונים יותר מטבלה אחת? אני אשיב באמצעות דוגמא – נניח ויש לי את עבלת הלקוחות שלי שבה השתמשתי כדוגמא במאמרים הקודמים:
+-------------+---------------+--------------+--------------+
| costumer_id | costumer_name | costumer_age | costumer_sex |
+-------------+---------------+--------------+--------------+
| 1 | moshiku | 21 | male |
| 2 | Haim | 22 | male |
| 3 | Yaakov | 19 | male |
| 4 | Dan | 19 | male |
| 5 | Dana | 42 | female |
| 6 | Rina | 24 | female |
| 7 | Omri | 9 | male |
+-------------+---------------+--------------+--------------+
הלקוחות האלו עושים קניות, הם קונים במכולת הדמיונית שלי, מוצרים שונים. אם אני רוצה לשמור את הקניות האלו, אני צריך להכניס אותם איכשהו למסד הנתונים שלי. מתכנת מתחיל יבוא ויאמר – למה שלא נוסיף שורה נוספת לטבלה שלנו? אך מדובר בהצעה בעייתית הן מהבחינה הפרקטית (קשה לשלוף את הנתונים ולעדכנם, טבלה גדולה ומסורבלת וכו') והן מהבחינה התיאורטית (מדובר בפשע בל יכופר במבני נתונים). הדרך הנכונה היא לבנות טבלה נוספת, נפרדת, של קניות. שהשם שלה הוא my_purchase:
+-------------+---------------+
| costumer_id | purchase_item |
+-------------+---------------+
| 5 | pants |
| 5 | shirt |
| 3 | shirt |
| 1 | shirt |
| 7 | pants |
+-------------+---------------+
כאשר יש לנו שורה של costumer_id (ה-id של הלקוח שרכש) ו-purchase_item שמכילה את מה שהוא רכש (מכנסיים או חולצה).
החוט המקשר שיש לנו בין שתי הטבלאות הוא ה-id של הלקוח (שהוא Foreign Key אבל אנו נגיע לכך בהמשך). נניח ואני רוצה לשלוף את הקניות של כל המשתמשים אך בצירוף הפרטים שלהם. מה שאני צריך לעשות זה לעשות select מתוך טבלת my_purchase ולהצמיד אליה את השמות של מי שרכש את הקניות. הנה התוצאה שאני רוצה להגיע אליה:
+-------------+---------------+-------------+---------------+--------------+--------------+
| costumer_id | purchase_item | costumer_id | costumer_name | costumer_age | costumer_sex |
+-------------+---------------+-------------+---------------+--------------+--------------+
| 5 | pants | 5 | Dana | 42 | female |
| 5 | shirt | 5 | Dana | 42 | female |
| 3 | shirt | 3 | Yaakov | 19 | male |
| 1 | shirt | 1 | moshiku | 21 | male |
| 7 | pants | 7 | Omri | 9 | male |
+-------------+---------------+-------------+---------------+--------------+--------------+
את זה אנו עושים באמצעות JOIN – אנו עושים select על טבלת my_purchase ואז מחברים אל תוצאות ה-costumer_id שלנו את התוצאות המתאימות מטבלת my_costumer. פשוט להדגים:
SELECT * FROM my_purchase JOIN my_costumer ON my_purchase.costumer_id=my_costumer.costumer_id;
כאשר אנו כותבים את ה-JOIN אנו צריכים גם לכתוב ON שמכיל לפי מה לעשות את ה-JOIN. במקרה שלנו – costumer_id.
INNER JOIN
כאשר אני כותב רק JOIN זה בדיוק כמו לכתוב INNER JOIN. אך מקובל דווקא לכתוב INNER JOIN ולא JOIN.
LEFT JOIN ו RIGHT JOIN
כאשר אנו עושים INNER JOIN אז הטבלה מראה לי רק את ההתאמות הקיימות, או בדוגמא שלנו רק לקוחות שיש להם קניות ולא את כל הלקוחות. אם אני רוצה לעשות בחירה של הכל ולא רק את התוצאות (בחירה שנקראת OUTER JOIN כיוון שהיא מביאה את כל התוצאות, גם אלו שלא בתוך הבחירה) אני צריך להשתמש ב-RIGHT JOIN או LEFT JOIN. ההבדל ביניהם פשוט ותלוי בשאילתא שלנו.
RIGHT JOIN
RIGHT JOIN לוקחת את כל התוצאות מהטבלה הימנית (זו שמצויינת מייד לאחר ה-RIGHT JOIN). למשל, השאילתא הזו:
SELECT * FROM my_purchase RIGHT JOIN my_costumer ON my_purchase.costumer_id=my_costumer.costumer_id;
השאילתא שלעיל זהה לחלוטין לשאילתת ה-INNER JOIN שנתתי קודם. אך כיוון שהיא RIGHT JOIN, היא תחזיר לי את כל התוצאות של הטבלה מימין (my_costumer) גם אם אין ל-costumer_id שלהן זכר בטבלת ה-my_purchase. התוצאה תהיה כזו:
+-------------+---------------+-------------+---------------+--------------+--------------+
| costumer_id | purchase_item | costumer_id | costumer_name | costumer_age | costumer_sex |
+-------------+---------------+-------------+---------------+--------------+--------------+
| 1 | shirt | 1 | moshiku | 21 | male |
| NULL | NULL | 2 | Haim | 22 | male |
| 3 | shirt | 3 | Yaakov | 19 | male |
| NULL | NULL | 4 | Dan | 19 | male |
| 5 | pants | 5 | Dana | 42 | female |
| 5 | shirt | 5 | Dana | 42 | female |
| NULL | NULL | 6 | Rina | 24 | female |
| 7 | pants | 7 | Omri | 9 | male |
+-------------+---------------+-------------+---------------+--------------+--------------+
שימו לב שחיים למשל לא עשה רכישות ואין לו רכישות על שמו ב-my_purchase ולפיכך הוא יופיע כ-NULL בטבלה.
LEFT JOIN הוא בדיוק כמו RIGHT JOIN רק שהוא יכיל את כל הטבלה השניה, זו שנמצאת משמאל ובמקרה שלנו: my_purchase.
בחירה של חלק מהשורות ב-JOIN
אני לא חייב לעשות SELECT * כמובן. אני יכול לבחור רק חלק מהשדות. אם אני רוצה לבחור שדות שהם זהים (כמו למשל costumer_id שקיים גם ב-my_costumer וגם ב-my_purchase) אז אני יכול לכתוב את שם הטבלה נקודה ואז את שם השדה. למשל:
SELECT my_purchase.costumer_id purchase_item, costumer_name,costumer_age
FROM my_purchase INNER JOIN my_costumer ON my_purchase.costumer_id=my_costumer.c
ostumer_id;
וזה יתן לי את התוצאה הבאה:
+---------------+---------------+--------------+
| purchase_item | costumer_name | costumer_age |
+---------------+---------------+--------------+
| 5 | Dana | 42 |
| 5 | Dana | 42 |
| 3 | Yaakov | 19 |
| 1 | moshiku | 21 |
| 7 | Omri | 9 |
+---------------+---------------+--------------+
תנאים ב-JOIN
כמובן שאפשר להשתמש בכל התנאים שלמדנו ב-JOIN כאשר התנאים חלים על הטבלה המאוחדת שיצרנו. למשל, אם אני רוצה לעשות מיון של הקניות של מי שגילו מתחת לגיל 20:
SELECT my_purchase.costumer_id purchase_item, costumer_name,costumer_age
FROM my_purchase INNER JOIN my_costumer ON my_purchase.costumer_id=my_costumer.c
ostumer_id WHERE costumer_age<20;
וזה יביא לי את התוצאה הבאה:
+---------------+---------------+--------------+
| purchase_item | costumer_name | costumer_age |
+---------------+---------------+--------------+
| 3 | Yaakov | 19 |
| 7 | Omri | 9 |
+---------------+---------------+--------------+
⚠️המדריכים כאן הם טעימה בלבד! יש ספר מקיף המלמד MySQL מרמת בסיס ועד רמה מתקדמת. הספר הדיגיטלי, שרלוונטי גם לכל מסדי הנתונים שעובדים עם SQL – זמין כאן כחלק מהפרויקט "ללמוד ג'אווהסקריפט בעברית" – זו הדרך הטובה ביותר ללמוד באופן מקיף MySQL.
במאמר הבא אנו נדבר על MySQL subqueries – לא להבהל! מדובר בנושא נעים וקל.