עזרה בשאילתת SQL

תשובה עזרה בשאילתת SQL

  • יום ראשון 15 יולי 2012 16:05
     
      קוד כלול
    אני עובד עם SQL SERVER 2008 ויש לי בעייה שאני בכלל לא יודע אם אפשר לעשות את זה.

    את השאילתה אני רושם כך:
    SELECT VideoTitle FROM AllMovies WHERE VideoName LIKE '%Harry.Potter%'

    וזה מחזיר לי את :

    Harry.Potter 1
    Harry.Potter 2
    Harry.Potter 3
    Harry.Potter 4

    עד כאן הכל טוב

    אני רוצה שזה יהיה הפוך כלומר לשלוח עליו Harry.Potter 4 או Harry.Potter 3 ולקבל בחזרה Harry.Potter.
    אני גם רוצה להצליח לשלוח אליו Harry.Potter 5 שלא קיים בבסיס הנתונים ולקבל בחזרה Harry.Potter כלומר לקחת את הסטרינג שלי ולבדוק האם הנתונים בבסיס הנתונים "מתלבשים" על הסטרינג שלי ואם כן אז להחזיר את הערך Harry.Potter

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

כל התגובות

  • יום ראשון 15 יולי 2012 16:17
     
      קוד כלול
    נסה כך:
    SELECT VideoTitle FROM AllMovies WHERE 'Harry.Potter' LIKE '%'+VideoName+'%';


    Blog: http://about.me/GeriReshef

  • יום ראשון 15 יולי 2012 16:48
     
     

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

    יש לי תוכנה שבניתי שכל פעם מקבלת מחרוזת אחרת לחיפוש בבסיס הנתונים והיא מקבלת מחרוזת כזאת לדוגמה Harry.Potter 6
    ובבסיס הנתונים אין לי את המחרוזת הזאת בשום טבלה או עמודה אבל כן יש לי את המחרוזת Harry.Potter.
    אז אני רוצה לקבל בחזרה את הערך Harry.Potter (רק ערך אחד בלי לבצע יותר מידי דברים)

    אני ייתן עוד דוגמה כי אני מבין שמשהו בהסבר שלי לא כל כך טוב.

    1. יש לי את המחרוזת "דני הולך לטיול בכל בוקר ובכל ערב"

    2. בבסיס הנתונים יש לי הערכים האילו:

        א. "דני הולך לטיול"
        ב. "משה הולך לטיול"
        ג. "ירון הולך לטיול"

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

    כמו שאני מבין את זה אז אני צריך לבדוק האם התא הראשון בבסיס הנתונים נמצא במלאו בתוך המחרוזת ששלחתי ואם כן אז להחזיר אותו.
    אם לא אז לבדוק את התא הבא וכך הלאה.....

    מקווה שזה היה ברור כי אני ממש זקוק לעזרה. אני משתגע עם זה כבר כמה ימים


    • נערך על-ידי MaorD יום ראשון 15 יולי 2012 16:50
    •  
  • יום ראשון 15 יולי 2012 17:13
     
      קוד כלול

    הא לך דוגמה:

    Create Table #T(S Varchar(50));
    Insert Into #T Select 'דני הולך לטיול';
    Insert Into #T Select 'משה הולך לטיול';
    Insert Into #T Select 'ירון הולך לטיול';
    
    Select * From #T Where 'דני הולך לטיול בכל בוקר ובכל ערב' Like '%'+S+'%';
    השאילתה בסוף מחזירה מהטבלה את 'דני הולך לטיול'.


    Blog: http://about.me/GeriReshef

  • יום ראשון 15 יולי 2012 17:25
    משיב
     
     

    מאור

    דרך אגב הפורום האחר ששאלת הוא בפורום בתפוז, ומי שענה לך שם הוא אותו אדם שענה לך כאן :-) גרי הוא המנהל פורום שם.

    בכל מקרה אם התשובה של גרי זה עדיין לא מה שאתה מבקש אז אני מציע שתעביר לנו DDL+DML

    כמו שגרי שם בתשובה שלו (אם הטבלאות כמו אצל גרי אז רק תסביר שוב מה אתה רוצה לקבל בסיום בדיוק כי אני מבין בדיוק כמו גרי גם כאן וגם בתפוז הבנתי אותו דבר ממך).


    signature

  • יום ראשון 15 יולי 2012 18:27
     
      קוד כלול

    ניסיון אחרון ואם זה לא יעבוד אז אני יבדוק את ה-DDL+DML (יותר נכון ילמד מה זה ואז ישאל שוב)

    כתבתי 3 שאילתות

    SELECT * FROM AllMovies WHERE FileName LIKE '%Tequila.Sunrise.DVDRip.XviD.avi%';
    SELECT * FROM AllMovies WHERE FileName LIKE '%Tequila.Sunrise.DVDRip.XviD%';
    SELECT * FROM AllMovies WHERE FileName LIKE '%Tequila.Sunrise%';

    השאילתה השניה והשלישים עובדים טוב מאוד ומחזירות את מה שאני רוצה (Tequila.Sunrise.DVDRip.XviD) שזה מה שכתוב בבסיס הנתונים באופן מדוייק.

    השאילתה השניה היא חיפוש מדוייק למה שאני מחפש אז אין לי בעיה למצוא את זה

    השאילתה השלישית היא חלק מהטקסט שמופיע בבסיס הנתונים ואז עם LIKE אני מצליח לקבל גם את הערך הנכון שזה כמו בשאילתה הקודמת (Tequila.Sunrise.DVDRip.XviD)

    אבל בראשון אני לא מקבל כלום כי יש לי את התוספת '.avi' ובגלל זה אני לא מוצא את הנתון בבסיס הנתונים.

    השאלה שלי היא איך אני יכול למצוא את הנתון הזה? (את הראשון)

    (עשיתי העתק הדבק מ-SQL Server Management Studio כך שבטוח שמה שעובד ומה שלא עובד באמת כך)

  • יום ראשון 15 יולי 2012 18:29
     
     הצעה לתשובה קוד כלול

    אחי, לא ככה אלא ככה:

    SELECT * FROM AllMovies WHERE FileName LIKE '%'+Tequila.Sunrise.DVDRip.XviD.avi+'%';
    SELECT * FROM AllMovies WHERE FileName LIKE '%'+Tequila.Sunrise.DVDRip.XviD+'%';
    SELECT * FROM AllMovies WHERE FileName LIKE '%'+Tequila.Sunrise+'%';


    Blog: http://about.me/GeriReshef

    • הוצע כתשובה על-ידי pituachEditor יום ראשון 15 יולי 2012 18:51
    •  
  • יום ראשון 15 יולי 2012 19:01
     
      קוד כלול

    עכשיו אני מקבל מלא הודעות שגיאה (עם הקוד שלך)

    Msg 4104, Level 16, State 1, Line 1
    The multi-part identifier "Tequila.Sunrise.DVDRip.XviD.avi" could not be bound.
    Msg 4104, Level 16, State 1, Line 2
    The multi-part identifier "Tequila.Sunrise.DVDRip.XviD" could not be bound.
    Msg 4104, Level 16, State 1, Line 3
    The multi-part identifier "Tequila.Sunrise" could not be bound.


    • נערך על-ידי MaorD יום ראשון 15 יולי 2012 19:02
    •  
  • יום ראשון 15 יולי 2012 19:05
     
     

    שמות העמודות שכתבת שגויים:
    כנראה שבטבלה Tequila אין עמודה Sunrise
    וכנראה גם אין משהו כזה- Tequila.Sunrise.DVDRip.XviD.avi (מה זה אמור להיות?).

    בין האחוזים יש לציין שמות של עמודות מהטבלה.


    Blog: http://about.me/GeriReshef

  • יום ראשון 15 יולי 2012 19:13
     
     

    אז נראה לי שאני ממש עושה כאן טעויות (רואים שאני מתכנת .NET ולא SQL)

    הנתון שאני רוצה לחפש = Tequila.Sunrise.DVDRip.XviD.avi

    העמודה שבא נמצאים הנתונים = FileName

    בסיס הנתונים = AllMovies

    בבסיס הנתונים יש את הערך הבא : Tequila.Sunrise.DVDRip.XviD

    דומה מאוד למה שאני מחפש רק בלי הסיומת של ה - avi.


    אם בין האחוזים אני מכניס את השמות של העמודות אז איפה אני מכניס את המחרוזת שאני מחפש ????
    • נערך על-ידי MaorD יום ראשון 15 יולי 2012 19:14
    •  
  • יום ראשון 15 יולי 2012 19:15
    משיב
     
     

    מאור אם היית מעלה לנו DDL+DML כמו שהצעתי לא היתה בעיה לתת לך שאילתה שמתאימה לטבלה שלך עם שמות שדות כמו שיש לך.

    תנסה להבין את הדרך שמבצעים חיבור של פרמטרים עם שרשרת. מזה לא משהו מורבכ וזה נכון לכל שפה ולא רק ל SQL. אותו דבר עושים ב c#,vb.net או JS או כל שפה אחרת.


    signature

  • יום ראשון 15 יולי 2012 19:21
     
     

    אני לעומת זאת- אינני מבין דבר בדוט נט..
    בכל מקרה- מה שצריך לציין בין האחוזים זה DBName.SchemaName.TableName.ColumnName 

    כמובן שאפשר לקצר, אבל בו נתחיל מהכי בטוח..
    SchemaName היא בדרך כלל dbo.
    העמודה ColumnName אמורה להיות טקסטואלית.


    Blog: http://about.me/GeriReshef

  • יום ראשון 15 יולי 2012 19:25
     
      קוד כלול

    לפי מה שהבנתי מה-DDL זה מה שאני צריך לשלוח

    create table AllMovies (
     
    [Title] nchar(100),
     
    [Description] nchar(2000),
     
    [FileName] nchar(200)
     
    )

  • יום שני 16 יולי 2012 06:28
     
     

    היי מאור.

    לפי מה שאני מבין אתה רוצה חיפוש מקורב ולא מדויק.

    זאת אומרת full text search

    אתה יכול להמשיך לקרוא כאן:

    http://blog.sqlauthority.com/2008/09/05/sql-server-creating-full-text-catalog-and-index/

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

    או לחליפין אם אתה מתכנת ב C# אתה יכול להשתמש ב lucence  או בתחליפו העברי

    http://www.code972.com/blog/hebmorph/

    נ.ב.

    יש סיבה הגיונית שאתה משתמש ב NCHAR ולא מ NVARCHAR או NTEXT ?

    • נערך על-ידי tetitu יום שני 16 יולי 2012 06:34
    •  
  • יום שני 16 יולי 2012 08:02
     
     

    תודה. נראה לי שהקישור שנתת זה מה שאני צריך (אני ילמד ממנו).

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

    אני עובד ב-.NET וזאת הפעם הראשונה שלי עם SQL (רואים שאני חדש אבל משגיאות לומדים)

    תודב רבה ואני מקווה שהקישור באמת יפתור לי את הבעיה או שאני פשוט יחזיר את כל הנתונים ויבנה פונקציה ב-#C שבטוח תעבוד לי :-) אבל אני לא רוצה להתייאש מ-SQL

  • יום שני 16 יולי 2012 09:55
     
     

    סבבה אם זה עזר לך אל תשכח לסמן תשובה למי שעזרו לך :)

    נ.ב.

    ההבדר בין CHAR ל VARCHAR הוא:

    CHAR תמיד יתפוס את מלא המקום ב SQL

    זאת אומרת שאם יש לי CHAR 30 שבתוכו אני שם "1234" אז הוא יתפוס מקום של 30 תווים

    ואם אני מגדיר VARCHAR 30 עם הערך "1234" אז הוא יתפוס רק 4 תווים.

    לגבי רשומה מסוג TEXT היא תמיד תתפוס 16 בייט ברשומה (ויתקנו אותי חכמים לגבי הגודל המדוייק) מכיוון שהערכים נשמרים מחוץ לרשומה.

  • יום שני 16 יולי 2012 12:06
    משיב
     
     תשובה קוד כלול

    כמו שכתבתי לך בתפוז עכשיו הדברים ברורים.

    ברגע שראיתי את ה DDL ששמת ולאור התוספת בתפוז שאצלך זה עובד בשרת אחד ולא בשרת אחר, אז היה ברור מה הבעיה!

    זה מה שקורה כשנותנים לנו לנחש
    תמיד תמיד תמיד תמיד כשאתה שואל שאלה ואתה רוצה תשובה מתאימה למה שיש לך תצרף לשאלה DDL+DML

    עתה נחזור לבעיה:

    ההגדרות אצלך מוסיפות רווחים ולכן אתה מבצע חיפוש "לא טוב" (הטעות היא בבחירה של סוג הטור ובהגדרות שלו). אתה יכול לשנות הגדרות כך ש CHAR לא יוסיף רווחים אבל עדין זה סוג של טור שלא מתאים לך בכלל לאפיון.

    אני מציע לך לקרוא מעט על ההבדל בין varchar לבין char. אתה בחרת סוג של טור שבברור אינו מתאים לך

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

    באותו היזדמנות כדאי לקרוא על טור מסוג NVARCHAR שאני בטוח שזה מה שאתה צריך ולא VARCHAR ובטח ובטח ובטח ובטח שלא CHAR של 100 תווים :-)

    לסיכום: שלב ראשון תעבור לשימוש בטור מסוג מתאים. שלב שני השאילתה של גרי תעבוד לך תמיד

    מקווה שזה יעזור :-) הנה כמה קישורים:

    הגדרה של "ריפוד" ברווחים (אם כן יוספו רווחים) עושים באמצעות:

    SET ANSI_PADDING { ON | OFF }

    http://msdn.microsoft.com/en-us/library/ms187403.aspx

    שאלות עם תשובות ברמה מאוד מאוד בסיסית על סוגים השונים שיש ב SQL

    http://www.sql-server-helper.com/faq/data-types-p01.aspx/


    signature

  • יום שני 16 יולי 2012 12:16
     
     

    ראיתי את התגובה בתפוז והייתי חייב להיכנס גם לכאן ולהגיד לך תודה רבה (שיניתי ל-NVARCHAR והכל עובד טוב מאוד) שוב תודה על הכל.

  • יום שני 16 יולי 2012 12:19
    משיב
     
      קוד כלול

    CHAR לא תמיד יתפוס את המקום המלא למשל במקרה של NULL

    כמו כן לגבי ריפוד ברווחים ניתן להגדיר את זה בעזרת

    SET ANSI_PADDING { ON | OFF }

    כמו כן לא מדוייק לגבי varchar מפני שהוא יתפוס את המקום של מספר התווים + 2 (לכן לפעמים בשרשרת של 2 תווים לא הגיוני לשמור ב VARCHAR כי רק התוספת של ה 2 תווים כבר תופסת כמו שמירה ב CHAR של 2 תווים)

    * גם זה לא מדוייק באופן מלא, כי יש ב PAGE גם HEADER-ים שנשמרים ועוד נתונים אבל לפחות זה החישוב הנהוג לבצע (אורך + 2) עבור כל רשומה של n/varchar. אם תחפש בפורום חיים העלה קישור לבלוג שהוא כתב בנושא של שמירת הנתונים בפועל ב PAGE-ים


    signature
    • נערך על-ידי pituachEditor יום שני 16 יולי 2012 12:21
    • נערך על-ידי pituachEditor יום שני 16 יולי 2012 12:56
    •  
  • יום שני 16 יולי 2012 12:22
     
      קוד כלול

    הי מאור. אני מתקשה להבין למה הפיתרון של גרי לא עזר לך. נסה את זה:

    SELECT * FROM AllMovies WHERE 'Tequila.Sunrise.DVDRip.XviD.avi' LIKE '%'+FileName+'%'
    מה זה מחזיר לך?
  • יום שני 16 יולי 2012 12:28
    משיב
     
     

    מאור לפי מה שאני הבנתי ממך בתפוז אתה לא צריך FULL TEXT SEARCH אלא חיפוש פשוט בדיוק כמו שגרי הציע לך מההתחלה. אולי אני טועה כמובן אז כדאי להבהיר האם אתה מחפש גם מילים דומות או רק מילים מדוייקות למשל.

    להבהרה למי שלא בטוח: FTS משמש לחיפוש לפי משמעות ולא לחיפוש של מילים מסויימות As Is It. לכן גם יש חשיבות מכרעת לכך שמשתמשים במילון מתאים לשפה שבה מחפשים ובמנוע FTS מתאים. למשל אם מחפשים את המילה "הולך" אז ב FTS צריכה להיות לנו היכולת לקבל את ההטיות של השורש "הלך" + הטיות של המילה כמו צורת הרבים שלה, ואפילו מילים נרדפות שאין כביכול קשר לאותיות של המילה שמחפשים (הכל תלוי בעד כמה מנוע ה FTS טוב). למשל אם מחפשים את מילה "הלכתי" שלא מכילה את "הולך" אז מנוע טוב של FTS יזהה שאלו מילים דומות ולכן ייתן ניקוד גם למילה זו ויחזיר את התוצאה בהתאם.

    כפי שכתב tetitu  לגבי העברית ו FTS של SQL הרי שיש כלים אחרים יעילים יותר, אם כי אני חושב (הרגשה ולא ידיעה) שהדברים השתפרו במערכת הפעלה 2008r2. שימו לב! FTS עושה שימוש במנוע חיצוני של מערכת ההפעלה למעשה Microsoft Search (MSSearch) service ואינו מנוע פנימי של ה SQL. אנחנו רק מפעילים אותו דרך ה SQL לשם נוחות.

    כתבתי כמה פעמים של FTS כאן בפורום לעומק וניתן למצוא את זה בחיפוש


    signature

    • נערך על-ידי pituachEditor יום שני 16 יולי 2012 12:29
    •  
  • יום שני 16 יולי 2012 12:31
    משיב
     
     

    Ivan Radchenko הפתרון לא עבד אצלו בגלל רווחים שנוספו לו בשדה char :-)

    זה כל הסיפור


    signature

    • נערך על-ידי pituachEditor יום שני 16 יולי 2012 12:32
    •