Menu

SQLite INNER JOIN: שילוב שורות מכמה טבלאות

איך INNER JOIN עובד ב-SQLite: המודל המנטלי, פסוקית ON, חיבור של שלוש טבלאות וקיצור הדרך USING.

בדף הזה יש עורכים שאפשר להריץ - לערוך, להריץ ולראות את הפלט מיד.

JOIN תופר שתי טבלאות יחד

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

INNER JOIN הוא סוס העבודה. הוא מצמיד שורות משתי טבלאות בכל מקום שבו תנאי מתקיים, ומשמיט את כל השאר.

שלושה לקוחות, שלוש הזמנות, אבל ל-Chen אין הזמנות, ולכן Chen לא מופיע. זה החלק ה"פנימי": רק שורות שנמצאה להן התאמה שורדות.

המודל המנטלי: מתאימים שורות, ואז מסננים

קראו INNER JOIN כך: קחו כל שורה מהטבלה הראשונה, הסתכלו על כל שורה מהטבלה השנייה, ושמרו את הזוג רק כשתנאי ה-ON מתקיים. מבחינה רעיונית זו מכפלה קרטזית ענקית ואחריה סינון. SQLite לא עושה את זה כך בפועל (היא משתמשת באינדקסים כשהיא יכולה), אבל המודל נכון כדי לצפות מה ייצא.

כמה הרגלים שכדאי לאמץ כאן:

  • תנו כינויים לטבלאות (customers AS c) כשתזכירו אותן יותר מפעם אחת. זה מפחית רעש.
  • ציינו את הטבלה לפני העמודה (c.name, o.total) כשסביר ששתי הטבלאות מכילות אותה.
  • הסדר ב-ON o.customer_id = c.id לא משנה: c.id = o.customer_id עובד אותו דבר.

INNER JOIN מול JOIN

ב-SQLite (וב-SQL התקני), JOIN לבדו פירושו INNER JOIN. מילת המפתח INNER היא אופציונלית.

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

ON מול USING

כשלעמודות החיבור יש אותו שם בשתי הטבלאות, USING (column) קצר יותר מ-ON a.col = b.col:

USING (customer_id) עושה שני דברים: מתאים לפי customer_id שווה, וממזג את העמודה כך שהיא מופיעה פעם אחת בתוצאה. השתמשו בו כששני הצדדים באמת משתמשים באותו שם. הישארו עם ON כשהשמות שונים (orders.customer_id = customers.id) או כשהתנאי הוא יותר משוויון יחיד.

חיבור שלוש טבלאות

משרשרים JOIN על ידי הוספת פסוקיות JOIN ... ON .... כל אחת מקשרת את התוצאה המצטברת לטבלה נוספת.

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

סינון עם WHERE

ON אומר איך להצמיד שורות. WHERE מסנן את התוצאה המוצמדת. ב-INNER JOIN דווקא, תנאי נוסף ב-ON או ב-WHERE מייצר את אותן שורות, אבל המוסכמה היא לשמור את תנאי החיבור ב-ON ואת סינוני השורות ב-WHERE.

זה נקרא כמו "חברו לקוחות והזמנות, ואז השאירו רק לקוחות מבריטניה שההזמנה שלהם מעל 20". שני תפקידים, שתי פסוקיות, והאני העתידי שלכם יודה לכם. (ברגע שמתחילים לכתוב LEFT JOIN, ההבחנה בין ON ל-WHERE מפסיקה להיות קוסמטית, אבל זה בעמוד הבא.)

כמה תנאים ב-ON

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

ההזמנה שבוטלה נעלמת כי התנאי השני נכשל. ב-INNER JOIN אפשר באותה מידה לכתוב WHERE o.status = 'paid' ולקבל את אותה תוצאה. גרסת ה-ON שומרת את הלוגיקה של "מה נחשב התאמה" קרוב ל-JOIN.

מלכודות נפוצות

כמה דברים שמכשילים אנשים:

  • שכחה של פסוקית ה-ON. FROM a INNER JOIN b בלי ON היא שגיאת תחביר ב-SQLite. (פסיק לבד, FROM a, b, כן מתקמפל, נותן cross join, וכמעט אף פעם הוא לא מה שרציתם.)
  • כפילויות לא צפויות. אם ללקוח יש שלוש הזמנות, השם שלו מופיע שלוש פעמים בתוצאה. זו התנהגות נכונה של JOIN, לא באג. בצעו צבירה עם GROUP BY אם אתם רוצים שורה אחת לכל לקוח.
  • שורות חסרות. אם לקוח היה אמור להופיע ולא הופיע, תנאי החיבור לא התקיים: בדקו אם יש NULL בעמודות החיבור, או השתמשו ב-LEFT JOIN.
  • שמות עמודות דו-משמעיים. SELECT id FROM customers JOIN orders ON ... נכשל כי לשתי הטבלאות יש id. ציינו את הטבלה: c.id או o.id.

הצעד הבא: LEFT JOIN

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

שאלות נפוצות

מה עושה INNER JOIN ב-SQLite?

INNER JOIN מחזיר שורות שיש להן התאמה בשתי הטבלאות לפי תנאי ה-ON. שורות משני הצדדים שאין להן התאמה נשמטות. זו ברירת המחדל: JOIN ו-INNER JOIN הם אותו דבר ב-SQLite.

מה ההבדל בין INNER JOIN ל-LEFT JOIN ב-SQLite?

INNER JOIN שומר רק שורות שנמצאה להן התאמה. LEFT JOIN שומר כל שורה מהטבלה השמאלית וממלא ערכי NULL בצד הימני כשאין התאמה. השתמשו ב-INNER JOIN כשהיעדר התאמה פירושו 'דלגו על השורה', וב-LEFT JOIN כשהיעדר התאמה פירושו 'הציגו אותה בכל זאת'.

אפשר לבצע INNER JOIN על שלוש טבלאות ב-SQLite?

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

מתי כדאי להשתמש ב-USING במקום ב-ON?

USING (column) הוא קיצור דרך כשלעמודת החיבור יש אותו שם בשתי הטבלאות. הוא תמציתי יותר ומאחד את העמודה הכפולה לעמודה אחת בפלט. השתמשו ב-ON בכל פעם ששמות העמודות שונים או שצריך תנאי מורכב יותר.

איור של שפות התכנות ב-Coddy

ללמוד תכנות עם Coddy

להתחיל