תאריכים ו SQL

רענני1975

New member
תאריכים ו SQL

שלום לכל חברי הפורום. יש לי טבלא שמכילה שדות עם תאריכים מפוזרים לאורך כל השנה. אני מנסה להריץ שאילתה ב SQL (כותב ב VB פשוט עם אקסס) שתוציא לי את כל התאריכים הקיימים בטבלא מסודרים מהיום והלאה ולאחר מכן את כל התאריכים מהישן ביותר ועד היום (לא כולל). כלומר אם היום התאריך הוא 11/12/2011 אז תוצאות צריכות להראות ככה: 11/12/2011 30/12/2011 05/01/2011 01/12/2011 מה שאני עושה היום זה משתמש בשתי שאילתות, הראשונה: select * from SomeTbl where Full_date>=#"&date()&"# order by Full_date הבעיה היא שזה מוציא לי רק עד סוף השנה ולא ממשיך הלאה ולכן אני חייב להוסיף גם את השניה: select * from SomeTbl where Full_date<#"&date()&"# order by Full_date חייבת להיות איזה דרך לוגית להוציא את הכל בשאילתה אחת, לא?!??! או שיש איזה פונקציה שאני לא מכיר? תודה!
 

sinaiy

New member
הניחוש שלי,

הערכים הם לא בפורמט של תאריכים. ולכן הSQL ממיין לפי מיון מילוני. זה עובד טוב כאשר התאריכים רשומים כ 2011-11-23 וכו' ולא טוב אחרת. תבדוק שהערכים הם באמת כתאריכים. ואם לא אז תהפוך אותם לכאלה (בשאילתה לפחות)
 

רענני1975

New member
תודה אבל התאריכים בסדר, זו לא הבעיה

את כל בעיית התאריכים סידרתי עם פונקציית FORMAT. האמת שה SQL נראה ככה (פשוט לא רציתי להכנס לזה): select * from SomeTbl where Full_date>=Format(#"&date()&"#,'mm/dd/yyyy') order by Full_date והשני כך: select * from SomeTbl where Full_date<Format(#"&date()&"#,'mm/dd/yyyy') order by Full_date השאלה שלי היא סה"כ האם ניתן לעשות את שתי השאילתות האלה בשאילתה אחת במקום שתיים??
 

sinaiy

New member
לא ממש ברור

אם אתה רוצה את כל התאריכים תזרוק את ה WHERE אם אתה רוצה שהסדר יהיה קודם תאריכים מהיום ואח"כ תאריכים עד היום יש לך 2 אפשרויות 1. לעשות UNION על 2 השאילתות. הכי קל הכי פשוט. order by CONCAT(date<curdate(),date_format(date,'%Y-%m-%d) ASEC או משהו דומה. התוצאה לפי מיון מילוני של הערך בסדר עולה היא מה שאתה מחפש.
 

רענני1975

New member
ניסיתי UNION וזה לא ממש עזר

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

sirpad

New member
אתה צריך להמיר את הפרש התאריך

למספר שיתמוך בדרישות הסדר שלך. גם UNION יעבוד, פשוט תאריכים בעלי הפרש ימים חיובי נשארים כמו שהם, בעוד שתאריכים בעלי הפרש ימים שלילי מקבלים תוספת של מספר גבוה מאוד, והופכים לחיוביים. כך ש: היום = 0 מחר = 1 מחרתיים = 2 אתמול = 10001 שלשום = 10002
 

sirpad

New member
פתרון בשימוש datediff ו cte

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

רענני1975

New member
וואו סירפד אני חייב לנסות את מה שאמרת

נראה מסובך ואני מקווה שה UNION בסופו של דבר לא פשוט יאחד הכל לטבלא אחת ויסדר את התאריכים מהישן לחדש?
 

pitoach

New member
כתבתי כבר בעבר לגבי החיסרון של ROW_NUMBER

כמה פעמים כאן בפורום וגם בבלוגים שונים (חיסרון לעיתים). השימוש ב ROW_NUMBER יפה אבל לעיתים יכול להיות להיות בעיה מאוד רצינית בשל הצורך ביצירת שדה חדש למעשה (שדה התוצאה של ה ROW_NUMBER) ויש מאוד להיזהר בשימוש בו בעיקר במצבים בהם אין אינדוקס על השדה בפנקציות החלון במקרה הנוכחי למשל מדובר בדוגמה נוספת לכך שהפתרון שהוצע אינו מומלץ בטבלה לא מאונדקסת ולכן תמיד מומלץ לבדוק את הנושא כשבוחרים לייצר שדה חדש בזמן ההרצה. בכל מקרה כאן הפתרון מאוד קל וניתן לבצע אותו פשוט על ידי שימוש ישיר ב ORDER BY
ניתן לראות כאן פתרון פשוט מאוד וכן השוואה בין הפתרון שהוצע מעל לפתרון הישיר הפשוט http://ariely.info/dnn/Blog/newForumsFAQ/ForumsFAQ349/tabid/158 ההבל במשאבים בטבלה קטנה הוא פי 3 לרעת השימוש ב ROW_NUMBER וככל שהטבלה תגדל ההבדלים יגדלו * אני שוב מדגיש שכל שאילתה היא מותאמת למצב מסויים ומדובר בדוגמה ספציפית של טבלה כפי שהוצגה (טבלה פשוטה ללא אינדוקס) ומקרה ספציפי
 

sirpad

New member
אאלט דיברתי על 2 הפתרונות הנל

אני עדיין מאמין שהפתרון בשימוש cte הוא נקי יותר וקריא יותר, אמנם לא בדקתי ביצועים של cte מול פקודת case, אבל מה שכן השימוש בcte לא מכריח שימוש ב row_number, כך שניתן לשלב datediff נקי עם cte, ואז יש לנו 3 אופציות לבדוק מה טוב יותר. מה שכן אין ספק ששימוש בcte יוצר תכנית עבודה מורכבת יותר לעין, אבל הפררליזם יוצר מצב שאולי דווקא המורכבות, נותנת אפשרות למנוע להריץ את השאילתה מהר יותר? שווה בדיקה.
 

pitoach

New member
תסתכל על האחוזים כדי לראות השוואה של מיטוב

כשמריצים כמה שאילתות ביחד מקבלים בתוכנית ההרצה של מנוע המיטוב של שרת ה SQL את החלק היחסי של ההשקעה בכל שאילתה. לכן שמתי את השאילתה שלך ביחד עם שאילתה ישירה וניתן לראות שמדובר כמעט פי 3 יותר משאבים. כאמור ככל שמספר הרשומות יגדל ההבדל יכול להיות אפילו הרבה יותר גדול * מה שנראה בעין בלי לבדוק לעומק לא מעניין
למרות שזה מצביע על יותר פעולות ולכן בדרך כלל יותר משאבים (לא בהכרח). מה שמעניין זה לאות את התוכנית ולהבין מה אומרת כל פעולה שם + ניתן לבדוק אחוזים כשמשווים שאילתות. ** אין קשר ל CTE בעקרון וזה לא מקור הבעיה אלא השימוש ב ROW_NUMBER וכל החישובים בדרך בעקבות זאת (כמו סידור הנתונים ועוד). כמו שכתבתי קודם כאשר מוסיפים שדה חדש בשאילתה און ליין צריך לחשוב טוב ולבדוק אם הוא לא מכביד על השאילתה. אם ייצרת טבלה זמנית למשל שכולת שדה מחושב ורוצים לבצע סידור נתונים לפי השדה החדש או סתם לבחור נתון לפי תנאי על השדה החדש אז צריך לזכור שלטבלה החדשה אין אינדקסים ככל הנראה והפעולה יכולה להיות כבדה. *** אישית (נקודה זו היא עניין לדעה ולא קביעה) אני מוצא שהשאילתה שצירפתי הרבה יותר קלה לקריאה במקרה הנוכחי
בשום אופן השאילתה שצירפתי אינה המיטבית דרך אגב אלא רק דוגמה לפתרון של חישוב ישיר (שימוש מיידי בתוצאות החישוב) לעומת שימוש בהוספת שדה מחושב ואז ביצוע פעולות על שדה זה אחר כך.
 

pitoach

New member
שיםן לב שתוכנית ההרצה שהפעולות היקרות אצלך

הן הפעולות של המיון (SORT) שנובעות ישירות בעקבות השימוש ב ROW_NUMBER
 

כלליים

New member
הנה

פתרון אקססי כפי שבקשת.
SELECT TBL.תאריך FROM TBL ORDER BY IIf([תאריך]>=Date(),[תאריך]-Date(),[תאריך]);​
נסה אותו קודם בשאילתה רגילה, ואחרי שתעשה את ההתאמות, העבר אותו לVBA. אגב: כשמשרשרים מחרוזת בVBA, אין צורך להפריד את הפונקציה DATE ולשרשר אותה אם הסולמיות. זה לא כמו משתנה, כי גם DATE היא פונקצית SQL בדיוק כמו שהיא פונקצית VBA.
 

רענני1975

New member
חברים, בואו ניתן כבוד למר כלליים

שיחקת אותה, שורה אחת פשוטה שעושה בדיוק את מה שביקשתי. אני חייב להודות שלא הכרתי את הפונקציה הזו IIF ובטח שלא בשילוב עם ORDER BY. פשוט גאוני. עוד לפני שהבנתי מה בכלל אתה רוצה פשוט כתבתי אותה ב VBA אחד לאחד כמו שכתבת והופס, הכל עובד. תודה רבה!
 
למעלה