דילוג לתוכן
  • דף הבית
  • קטגוריות
  • פוסטים אחרונים
  • משתמשים
  • חיפוש
  • חוקי הפורום
כיווץ
תחומים

תחומים - פורום חרדי מקצועי

💡 רוצה לזכור קריאת שמע בזמן? לחץ כאן!
  1. דף הבית
  2. תכנות
  3. ארכיון code613m
  4. בעיה בשאילתה רקורסיבית SQL

בעיה בשאילתה רקורסיבית SQL

מתוזמן נעוץ נעול הועבר ארכיון code613m
4 פוסטים 2 כותבים 347 צפיות
  • מהישן לחדש
  • מהחדש לישן
  • הכי הרבה הצבעות
התחברו כדי לפרסם תגובה
נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
  • א מנותק
    א מנותק
    ארכיטקט
    כתב ב נערך לאחרונה על ידי
    #1

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

    --טבלה שאמורה להכיל את הנתונים ולעבד אותם לפני ההכנסה סופית למסד הנתונים
    	declare @WorkingPlacesDetailed table (ID int IDentity(1,1) ,FromYear int, FromMonth int, ToYear int,ToMonth int, WorkingPlaceID int,WorkingPlaceName nvarchar(500),DeductionsNumber int,ParentID int);
    	
    	--ממלא את הטבלה בנתונים לדוגמא
    
    	insert into @WorkingPlacesDetailed (FromYear , FromMonth , ToYear , ToMonth ,WorkingPlaceName)
    	Values(2005,5,2010,9,'פורום חרדי לעניני תיכנות') ,(2010,11,2013,4,'ארגון דעאש');
    	--מוסיף רשומה לכל שנה בטבלה זו עצמה על סמך ההפרש בין השנים
    	 with cte as
    	 (select ID, FromYear y,FromMonth ,ToYear ,ToMonth , FromYear,WorkingPlaceName  from @WorkingPlacesDetailed w where w.FromYear<w.ToYear
    	 union all
    	 select * from (select ID, 
    	 y+1 y,
    	 (case when y = FromYear then FromMonth else 1 end) as FromMonth,
    	 ToYear, 
    	 (case when y = ToYear then ToMonth else 12 end) as ToMonth,
    	 FromYear,WorkingPlaceName
    	 from cte ) as w  where  w.y <= w.ToYear)
    	 select y as Year,FromMonth , ToMonth , WorkingPlaceName ,ID as ParentID from cte Order by y ;
    

    פורסם במקור בפורום CODE613 ב15/12/2014 15:56 (+02:00)

    אידיאולוגיות גדולות נכנסות למטחנה של עולם המעשה ויוצאות ממנו בפירורים (ווינסטון צ'רצ'יל, סתם סתם, זה שלי)

    תגובה 1 תגובה אחרונה
    0
    • א מנותק
      א מנותק
      ארכיטקט
      כתב ב נערך לאחרונה על ידי
      #2

      את התוצאה הסופית אפשר לקבל כך

      insert into @WorkingPlacesDetailed (FromYear , FromMonth , ToYear , ToMonth ,WorkingPlaceName)
      	Values(2005,5,2010,9,'פורום חרדי לעניני תיכנות') ,(2010,11,2013,4,'ארגון דעאש');
      	--מוסיף רשומה לכל שנה בטבלה זו עצמה על סמך ההפרש בין השנים
      	 with cte as
      	 (select ID, FromYear y,FromMonth ,ToYear ,ToMonth , FromYear,WorkingPlaceName  from @WorkingPlacesDetailed w where w.FromYear<w.ToYear
      	 union all
      	 select * from (select ID, 
      	 y+1 y,
      	  FromMonth,
      	 ToYear, 
      	 ToMonth,
      	 FromYear,WorkingPlaceName
      	 from cte ) as w  where  w.y <= w.ToYear)
      	 select y as Year,(case when y  = FromYear then FromMonth else 1 end) as FromMonth, (case when y = ToYear then ToMonth else 12 end) as ToMonth , WorkingPlaceName ,ID as ParentID , ToYear from cte Order by y ;
      

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

      פורסם במקור בפורום CODE613 ב15/12/2014 17:29 (+02:00)

      אידיאולוגיות גדולות נכנסות למטחנה של עולם המעשה ויוצאות ממנו בפירורים (ווינסטון צ'רצ'יל, סתם סתם, זה שלי)

      תגובה 1 תגובה אחרונה
      0
      • S מנותק
        S מנותק
        softs
        כתב ב נערך לאחרונה על ידי
        #3

        ברגע שזה הפך לשאלה תיאורטית - זה התחום שלי . . .

        בהחלט שישנו הגיון בכל זה - אבל הוא די מורכב - אנסה לעשות סדר

        ישנן שתיים וחצי בעיות בדרך שבה ניסית לראשונה לפתור את הבעיה:

        א. אתה מצפה לבצע מניפולציה על השורה הראשונה בכל מקום עבודה (להפוך את החודש ל 12) אבל את ה CASE שלך אתה שם רק בחלק השני של ה UNION והשורות האלו בכלל נבחרות בחלק הראשון שלו

        ב. שכפלת את השדה FROMYEAR לשדה Y על מנת לבצע את המניפולציה על Y ולהשאיר את השדה המקורי לתצוגה ללא מניפולציה בכל השורות, מה שלא עשית בשדה TOMONTH ומכיוון שזו ריקורסיה זה גרם לכך שכשאתה מגיע לשורה האחרונה עבור מקום העבודה הערך בשדה TOMONTH נלקח מהשורה הקודמת שעשתה עליו מניפולציה ל 12 - ז"א התנאי ב CASE עובד אבל הערך שביקשת ממנו להביא הוא כבר לא הערך המקורי

        ג. לא אהבתי את התת שאילתה אבל זה כבר עניין של טעם

        הפתרון שלי הוא כזה

        א. לשים באופן קשיח את החודש 12 ב TOMONTH בחלק הראשון של ה UNION ולשים 1 קשיח ב FROMMONTH בחלק השני של ה UNION

        ב. להפריד את FROMMONTH לשדה נוסף שלא יבוצעו עליו מניפולציות לאורך הריקורסיה ואותו לשים בתנאי

        ג. לשים Y+1 בכל השוואה ולחסוך את התת שאילתה

        מה שאני חייב להודות שהפתרון של CASE בשאילתה הסופית הוא לא רע בכלל, לכן אני אוהב שהעניינים הופכים להיות עקרוניים ואפשר להתפלפל בלי לתת למציאות להפריע :lol:

        הדוגמה שלי:

        --טבלה שאמורה להכיל את הנתונים ולעבד אותם לפני ההכנסה סופית למסד הנתונים
            declare @WorkingPlacesDetailed table (ID int IDentity(1,1) ,FromYear int, FromMonth int, ToYear int,ToMonth int, WorkingPlaceID int,WorkingPlaceName nvarchar(500),DeductionsNumber int,ParentID int);
             
            --ממלא את הטבלה בנתונים לדוגמא
            insert into @WorkingPlacesDetailed (FromYear , FromMonth , ToYear , ToMonth ,WorkingPlaceName)
            Values(2005,5,2010,9,'פורום חרדי לעניני תיכנות') ,(2010,11,2013,4,'ארגון דעאש');
            --מוסיף רשומה לכל שנה בטבלה זו עצמה על סמך ההפרש בין השנים
             with cte as
             (select ID, FromYear y,FromMonth ,ToYear, ToMonth m, 12 ToMonth, FromYear,WorkingPlaceName  from @WorkingPlacesDetailed w where w.FromYear<w.ToYear
             union all
             select ID, 
             y+1 y,
             1 FromMonth,
             ToYear,
        	 m,
             (case when y+1 = ToYear then m else 12 end) as ToMonth,
             FromYear,WorkingPlaceName
             from cte w where w.y+1 <= w.ToYear)
        	 select y as Year,FromMonth , ToMonth , WorkingPlaceName ,ID as ParentID from cte Order by y
        

        פורסם במקור בפורום CODE613 ב16/12/2014 02:00 (+02:00)

        תגובה 1 תגובה אחרונה
        1
        • א מנותק
          א מנותק
          ארכיטקט
          כתב ב נערך לאחרונה על ידי
          #4

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

          פורסם במקור בפורום CODE613 ב16/12/2014 09:59 (+02:00)

          אידיאולוגיות גדולות נכנסות למטחנה של עולם המעשה ויוצאות ממנו בפירורים (ווינסטון צ'רצ'יל, סתם סתם, זה שלי)

          תגובה 1 תגובה אחרונה
          0

          בא תתחבר לדף היומי!
          • התחברות

          • אין לך חשבון עדיין? הרשמה

          • התחברו או הירשמו כדי לחפש.
          • פוסט ראשון
            פוסט אחרון
          0
          • דף הבית
          • קטגוריות
          • פוסטים אחרונים
          • משתמשים
          • חיפוש
          • חוקי הפורום