SQL: שאילתה שתחזיר רשומות מספרים או תאריכים מתוך טווח נתון
-
אני שמח שהתחושות שלי היו נכונות, למרבה המזל יש דרך לעשות את זה ב sql נקי במידת האפשר.
with cte as (select 1 i union all select i+1 i from cte where i < 5) select dateadd(YEAR, i-1, '2010-01-01') from cte
מקור
אז מבחינתי הנושא נפתר, ואגב זה דבר שימושי ביותר למשתמשי SQL ואני חושב שיש כאן מן הבשורהפורסם במקור בפורום CODE613 ב25/01/2014 22:29 (+02:00)
-
זה נקרא CTE רקורסיבי, תחביר די מופשט וקצת קשה להבנה אבל שימושי מאוד ורב עוצמה. יש דומים לו בהרבה שפות תיכנות מבחינת עצם הביצוע, אבל ב SQL זה יחסית חדש ונועד לחסוך שימוש גס בלולאה. אני עוד לא הבנתי אותו עד הסוף, מקוה שדוד ל.ט. יכתוב איזה מדריך טוב בנושא...
כאן יש תיעוד רשמי MSDN
כאן יש מדריך בקוד פרוייקטכל היתר תשאלו את רבי שרגא יהושע העשיל מגוגל :lol:
פורסם במקור בפורום CODE613 ב26/01/2014 09:43 (+02:00)
-
OK זה נראה שאני היחיד שמכיר - ויש לי טריקים נוספים אפילו . . . <!-- s8-) --><img src="{SMILIES_PATH}/icon_cool.gif" alt="8-)" title="מגניב" /><!-- s8-) -->
אגב שלא תגידו שלא אמרתי - התכונה הזו כמעט בת עשר (מ 2005) . . .
ואני הקטן אנסה להסביר:
הגדרה של CTE עשית על ידי שימוש במילה WITH כמו בדוגמה
היא מגדירה למעשה VIEW זמני שקיים רק עד אחרי שמתשאלים אותו פעם אחת ואז נעלם
תכונה ייחודית שלו היא שאפשר לקרוא ל VIEW מתוך עצמו מה שלמעשה הופך אותו לבעל יכולת רקורסיבית
מעבר לכך הכל פועל כמו שאילתה רגילה
בשורה הראשונה אתה למעשה בוחר את השורה הראשונה שלך ואז ב UNION מחבר אליה את הבאות בתור
לפי הלוגיקה שלך לדוגמה אם בחרת יום מסוים תרצה לחבר אליו את היום הבא או הקודם וכו'
דבר נוסף שצריך לשים לב לשים TERMINATOR כמו בכל רקורסיה, אחרת ב 100 הוא עף או שמגדירים MAX RECURSION גדול יותר מ100
במקרה של הדוגמה שהובאה >5 זה הטרמינייטוראחד הדברים המגניבים שזה משמש הוא עבור שליפת עץ מטבלה שטוחה ושרשור הנתיבים של העלים
לדוגמה אם יש טבלת עובדים ויש ID לכל עובד ועמודה שמכילה את ה ID של המנהל של אותו עובד וגם למנהל יש מנהל ולמעלה בקודש וכו'
לבנות מזה עץ ייראה בערך ככה : (אני ממליץ למי שרוצה להבין ליצור ממש טבלה ולנסות את השאילתה)WITH cte (ID,MID,path) AS ( SELECT [EmployeeID],[ManagerID], CAST([First Name] + ' ' + [Last Name] AS NVARCHAR(MAX)) FROM Employees WHERE [ManagerID] IS NULL UNION ALL SELECT [EmployeeID],[ManagerID], CAST(path + '\' + [First Name] + ' ' + [Last Name] AS NVARCHAR(MAX)) FROM Employees INNER JOIN cte ON ID = [ManagerID] ) SELECT * FROM cte
הקוד הזה בוחר את הבוס כשורה ראשונה ואז בריקורסיה יורד בעץ הארגוני עד שלעובד אין יותר JOIN לכפופים לו
מקווה עזרתי ולא בלבלתי . . .פורסם במקור בפורום CODE613 ב30/07/2014 23:17 (+03:00)
-
הנה היום יצא לי להשתמש בזה שוב, והפעם כשאני צריך לקבל רשימה של ערכים שנמצאים בין שני שדות, כלומר יש לי טבלה שמכילה שדה משנה, ושדה עד שנה, כשאני צריך לקבל רשימה של כל השנים אני משתמש בקוד הנפלא הזה:
with cte as (select c.FromYear i,ID, ToYear from CaseHandlingDates c union all select * from (select i+1 i,ID,ToYear from cte ) as c where c.i <= c.ToYear) select i , ID , ToYear from cte order by ID
פורסם במקור בפורום CODE613 ב22/10/2014 12:33 (+03:00)