Menu

CTE ב-SQLite: הסבר על פסוקית WITH

איך Common Table Expressions עובדים ב-SQLite: שימוש ב-WITH כדי לתת שם לתת שאילתות, לשרשר כמה CTE ולכתוב שאילתות שנקראות מלמעלה למטה.

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

CTE היא תת שאילתה עם שם

Common Table Expression (CTE) היא תת שאילתה שהוצאתם החוצה ונתתם לה שם. במקום לקנן SELECT בתוך SELECT אחר, מגדירים אותה למעלה עם WITH, נותנים לה שם, ואז משתמשים בשם הזה בשאילתה הראשית כאילו היה טבלה.

המבנה תמיד זהה:

קראו את זה מלמעלה למטה: קודם בונים תוצאה עם שם, customer_totals, ואז שואלים את התוצאה הזו. ה-CTE מתנהגת כמו view זמני שקיים רק לאורך הפקודה הזו.

אותה שאילתה בלי CTE

הנה אותה לוגיקה כתובה כתת שאילתה, כדי שתוכלו לראות מה ה-CTE מחליפה:

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

כמה CTE בשאילתה אחת

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

WITH אחד, ואחריו הגדרות CTE מופרדות בפסיקים. ה-CTE השנייה (big_spenders) קוראת מהראשונה (customer_totals) בדיוק כמו שקוראים מטבלה. ה-SELECT הראשי בא אחרי הגדרת ה-CTE האחרונה.

טעות נפוצה: לכתוב שוב WITH לפני ה-CTE השנייה. אל תעשו את זה: זו שגיאת תחביר. WITH אחד מכסה את כולן.

פנייה ל-CTE יותר מפעם אחת

כאן CTE באמת עוקפות את תתי השאילתות. אם צריך את אותה תוצאת ביניים בשני מקומות, CTE מאפשרת לחשב אותה פעם אחת ולפנות אליה פעמיים:

פונים ל-CTE פעמיים: פעם אחת כדי לחשב את הממוצע, ופעם כמקור הראשי. בלי ה-CTE, הייתם משכפלים את שאילתת ה-GROUP BY, וכל שינוי בה היה צריך להיעשות בשני מקומות.

CTE עם INSERT, UPDATE ו-DELETE

CTE הן לא רק ל-SELECT. אפשר לשים פסוקית WITH לפני INSERT, UPDATE או DELETE כדי להשתמש בתת שאילתה עם שם בפעולת כתיבה:

ה-CTE מתארת אילו שורות לסמן. ה-INSERT ... SELECT משתמש בה כמקור. אותו טריק עובד עם DELETE FROM ... WHERE id IN (SELECT id FROM cte) למחיקות בשלבים, כשהלוגיקה שבוחרת את השורות מסובכת.

מתי להשתמש ב-CTE

כמה כללי אצבע:

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

מתי לא לטרוח:

  • תת שאילתה פשוטה אחת שמשמשת במקום אחד. WHERE id IN (SELECT id FROM ...) בסדר גמור כמו שהוא.
  • שאילתות קריטיות לביצועים, שבהן כבר וידאתם שכתיבת הלוגיקה בתוך השאילתה עוזרת. בדרך כלל SQLite מתייחסת ל-CTE כמחסום אופטימיזציה פחות מכמה מסדי נתונים אחרים, אבל בנתיבים חמים שווה לבדוק עם EXPLAIN QUERY PLAN.

דוגמה מלאה

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

שתי CTE, וכל אחת עושה דבר אחד. ה-SELECT הראשי מעצב את התוצאה. אפשר לקרוא את השאילתה מלמעלה למטה ולהבין כל שלב בפני עצמו, וזה כל הרעיון של CTE.

הבא בתור: CTE רקורסיביות

כל מה שראינו עד עכשיו היה CTE רגילה: תת שאילתה עם שם, שמחושבת פעם אחת. SQLite תומכת גם ב-WITH RECURSIVE, שבה CTE פונה לעצמה כדי לעבור על היררכיות, לייצר רצפים או לעבור על גרפים. זה העמוד הבא.

שאלות נפוצות

מה זה CTE ב-SQLite?

Common Table Expression היא תת שאילתה עם שם שיושבת בראש פקודת SELECT, INSERT, UPDATE או DELETE. מציגים אותה עם מילת המפתח WITH, נותנים לה שם, ואז פונים לשם הזה בשאילתה הראשית כאילו היה טבלה. CTE הופכים שאילתות מורכבות לקריאות, כי הם מאפשרים לבנות את התוצאה צעד אחר צעד.

מה ההבדל בין CTE לתת שאילתה ב-SQLite?

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

אפשר לכתוב כמה CTE בשאילתה אחת ב-SQLite?

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

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

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

להתחיל