› פורומים › אפיון ופיתוח פריוריטי › חישוב ימי עבודה בפועל
- This topic has 22 תגובות, 2 משתתפים, and was last updated לפני 8 שנים, 2 חודשים by
אלמוני.
- Post
-
- ינואר 29, 2017 בשעה 7:09 pm
שלום,אני מעוניין לכתוב שאילתא שמציגה חישוב של מספר ימי עבודה מתאריך עד תאריך
עמודה אחת מציגה תאריך כניסה
עמודה שנייה מציגה תאריך יציאההחישוב אמור להיות כך שאם בין שני התאריכים קיימים ימים שהם שישי ושבת הספירה לא תכלול אותם.
לדוגמא : כניסה 01/01/17 יום א' יציאה 10/01/17 יום ג'
סה"כ ימים מתאריך עד תאריך 10 ימים ,
מתוכם שישי שבת – מופיע פעם אחת
סה"כ ימי עבודה בפועל 8 ימיםמהי הדרך הנכונה לחשב זאת?
האם באמצעות קרסור שלוקח את התאריך הראשון ומקפיץ בכל פעם ביום אחד ואם אותו יום הוא לא 6 או 7 אז הוא סופר אותו לתוך משתנה?האם באמצעות קרסור לבדוק מול טבלה שמחזיקה את כל ימות השנה שהם שישי שבת או אפילו חגים ואם התאריך מופיע בטבלה אז הוא לא נספר?
כיצד הייתם כותבים שאילתא שכזו?
- Replies
-
- ינואר 30, 2017 בשעה 1:29 am
לדעתי לא אמור להיות צורך לקרסור. (לעולם לנסות לא להשתמש בקרסור אם אפשר אחרת)הייתי הולך על משהו קרוב יותר לדבר השני שאתה מציע.
אני לא אתן פתרון מושלם כי לא חשבתי על הכל כאן אבל כך הייתי תוקף את זה.
חשוב לציין שאני לא יודע אם אתה צריך לבצע את החישוב רק עבור טווח תאריכים אחד או כמה – אבל בכל מצב לצערי לשפה של פריוריטי אין את האפשרויות שיש ב"טעמים" אחרים של SQL שנותנים לעשות כל מיני דברים "חכמים" תוך כדי אותה שאילתא.
קודם כל אפשר לנהל טבלה של ימי חופש/חג. לא צריכים לשים שם שישי/שבת כי את אלה אפשר לחשב.
הייתי עושה לולאה (לא קרסור) מהערך המספרי של התאריך הראשון (סוג DATE מחולק 24:00) עד האחרון. אם מדובר ב-א עד ה אז לספור. תקבל סה"כ ימי א-ה.
לעשות שאילתא (אין צורך לקרסור) להביא ספירה של ימי חג/חופש שהם ביום א-ה (תנאי בשאילתא) כדי לא לפחות ימים שממילא לא ספרת. ואת זה אתה מוריד מהחישוב הקודם.
וזהו… (?)
[ בבקשה לא לשלוח הודעות פרטיות במערכת - אני לא קורא אותן ]- ינואר 30, 2017 בשעה 1:32 am
אם אתה רוצה להיות מאוד מקיף אפשר לעצב את טבלת ה"יוצאים מן הכלל" לאפשר רישום של ימי שישי ושבת כימי עבודה (אני מזכיר בגלל מוצ"ש…) ולעשות עוד חישוב שיוסיף ימים כאלה לספירה…[ בבקשה לא לשלוח הודעות פרטיות במערכת - אני לא קורא אותן ]- ינואר 30, 2017 בשעה 12:46 pm
לפני הרבה שנים כתבתי את הקוד למטה – הוא בודק את ההפרש בשבועות ואז מחסיר 2 לכל שבוע. היום אני די בטוח שניתן לכתוב את הפונקציה בצורה יותר קלה ויותר ברורה.
:DAYS = 0;
:DATE = 01/01/88;
SELECT ((ORDSTATUSLOG.UDATE/24:00)*24:00),
(((ORDSTATUSLOG.UDATE/24:00)*24:00) - ORDERS.CURDATE)/1440 -
2 * (((WEEK (ORDSTATUSLOG.UDATE) / 100)*52 +
WEEK (ORDSTATUSLOG.UDATE) MOD 100) -
((WEEK (ORDERS.CURDATE) / 100) * 52 +
WEEK (ORDERS.CURDATE) MOD 100))
INTO :DATE, :DAYS
FROM ORDERS, ORDSTATUSLOG
WHERE ORDERS.ORD = :ORD
AND ORDERS.ORD = ORDSTATUSLOG.ORD
AND ORDSTATUSLOG.ORDSTATUS = -2
AND ORDSTATUSLOG.UDATE BETWEEN :$.FDT AND :$.TDT;
- פברואר 5, 2017 בשעה 12:37 am
תודה על התשובות,במידה ואני צריך לחשב כ- 1000 רשומות שלכל רשומה יש טווח תאריכים שנע בין 5 ימים ל – 21 ימים ,
האם לדעתכם תוכנית שכזו תהיה איטית בהכרח?
- פברואר 5, 2017 בשעה 1:33 am
גם אם עושים את זה לא נורא יעיל זה לא יקח המון זמן.
מי שיבין טוב יכול לבנות משהו שיקח מספר שניות גג.[ בבקשה לא לשלוח הודעות פרטיות במערכת - אני לא קורא אותן ]- פברואר 5, 2017 בשעה 11:12 pm
כמה שניות? מעט מדי זמן לא??קו המחשב שלי הוא כך:
מדובר על תעודות שהן קריאות שירות
לכל תעודה יש START DATE ו- END DATEשלב 1- אוסף את כל ה- DOC ואת תאריך ההתחלה והסיום של כל תעודה לפי תנאים שהגדרתי מראש ואת אלו מכניס לתוך טבלה זמנית
הטבלה מכילה : DOC , SDATE , EDATE , COUNTשלב 2- עובר על כל רשומה (מניח שכאן חייב קרסור ולא לופ … תקן אותי אם טועה) בכל רשומה לוקח את תאריך ההתחלה ועולה כל פעם באחד עד שמגיע לתאריך סוף . כל תאריך בודק מול טבלה שמכילה את כל ימי ה- שישי שבת ואת כל ימי החגים. במידה והתאריך שנבדק אינו מופיע בטבלה אז נכנס 1 למשתנה COUNT.
בסוף הריצה לרשומה מעדכן בעמודה COUNT את מספר ימי העבודה שנספרו בקרסור.שלב 3- מוסר את הטבלה הזמנית לדוח שאותו אני מענויין להציג ושם מוסיף את העמודות הנוסופת הרצויות.
מה דעתכם?
- פברואר 6, 2017 בשעה 12:47 am
אפשר לחסוך הרבה.ושם מוסיף את העמודות הנוסופת הרצויות.
איזה עמודות אתה צריך להוסיף?
אם הכל בא מ-DOCUMENTS או לכל הפחות לא תטצרך לעשות עוד קיבוץ יכול להיות שתוכל לחסוך קצת הכנה מראש ולעשות את עיקר העבודה בשיטה שאני אתאר בתוך הדו"ח אבל אם תעשה את זה בשלב ההכנה אז יהיה לך יותר חופש באופן כללי.בינתיים נניח שתעשה את הכל בשלבי הכנה.
הנחה נוספת: המקור שלך מסודר וכל תאריך סיום אחרי תאריך ההתחלה הקשור אליו.
אני הייתי עושה כך:
1. אוסף (MIN(SDATE ו- (MAX(EDATE על פני כל התעודות – נקרא לאלה MIN_SDATE ו-MAX_EDATE
2. עושה לולאה פשוטה (לא קורסור). מתחיל מ-MIN_SDATE, בוחן אם מדובר בששי/שבת (או בתאריך של חופשים אחרים) ומדלג אם כן. (אם יש מצב של ששי/שבת שיכול להיות יום עבודה אז חזור למה שכתבתי קודם על נושא זה ושנה כאן בהתאם). את התאריך הזה מכניסים לטבלה (אם לא מדלגים) – טבלת STACK מצויינת לזה, רק לעשות 0+ כדי להפוך את התאריך למספר. וחוזר עד שמגיע ל-MAX_EDATE.
3. עושה שאילתא על בסיס טבלת התעודות, וטבלת התאריכים מהשלב הקודם. עושים תנאי שהערך מטבלת התאריכים צריך להיות בין ה-SDATE וה-EDATE של התעודה (כולל, אם כך אתה רוצה) ואז קבץ לפי DOC ותוציא ספירה (COUNT) של מספר השורות שאתה מקבל לכל ערך של DOC. תוכל כאן לדעתי לדלג על שמירת SDATE ו-EDATE כי תוכל להביא אותם לדו"ח ביחד עם הערכים האחרים. כך שאתה צריך להכניס רק שני עמודות DOC ו-COUNT לאיזו טבלת לינק.
4. כמו שלב 3 שלךמה דעתך?
[ בבקשה לא לשלוח הודעות פרטיות במערכת - אני לא קורא אותן ]- פברואר 20, 2017 בשעה 9:34 pm
שלום יצחק
לא הבנתי כיצד אתה מדלג בכל פעם ביום מתאריך ההתחלה- פברואר 20, 2017 בשעה 10:31 pm
אתה מתכוון לשלב 2 איך עוברים על כל התאריכים ללא קורסור?אם לא בבקשה לכתוב קצת על מה שכן הבנת ואיפה אתה נתקע.
[ בבקשה לא לשלוח הודעות פרטיות במערכת - אני לא קורא אותן ]- פברואר 21, 2017 בשעה 4:35 pm
כתבתי2. עושה לולאה פשוטה (לא קורסור). מתחיל מ-MIN_SDATE, בוחן אם מדובר בששי/שבת (או בתאריך של חופשים אחרים) ומדלג אם כן. (אם יש מצב של ששי/שבת שיכול להיות יום עבודה אז חזור למה שכתבתי קודם על נושא זה ושנה כאן בהתאם). את התאריך הזה מכניסים לטבלה (אם לא מדלגים) – טבלת STACK מצויינת לזה, רק לעשות 0+ כדי להפוך את התאריך למספר. וחוזר עד שמגיע ל-MAX_EDATE.
להלן דוגמה בסיסית של לולאה זו, ללא ההכנסה לטבלה. שמתי SELECT כדי להדגים.
:MIN_SDATE = 01/01/17 ;
:MAX_EDATE = 21/02/17 ;:LOOP_DATE = :MIN_SDATE ;
LABEL 1 ;
GOTO 2 WHERE DAY(:LOOP_DATE) IN (6,7) ; /* skip next section if Fri/Sat */SELECT :LOOP_DATE FROM DUMMY ASCII ;
LABEL 2 ;
:LOOP_DATE = :LOOP_DATE + 1440 ; /* add one day */
LOOP 1 WHERE :LOOP_DATE <= :MAX_EDATE ; /* continue to next day unless last */
[ בבקשה לא לשלוח הודעות פרטיות במערכת - אני לא קורא אותן ]- פברואר 21, 2017 בשעה 4:59 pm
- פברואר 21, 2017 בשעה 6:49 pm
מסכים
אבל אני נוקט בגישה שלי כי תומך בקלות בהורדת ימים נוספים שלא ימי עבודה אם רוצים.
ועוד אני לא בדיוק הבנתי איך החישוב שלך עובד אז לא התייחסתי אליו.[ בבקשה לא לשלוח הודעות פרטיות במערכת - אני לא קורא אותן ]
- יש להתחבר למערכת על מנת להגיב.