שליפת נתונים מטבלה עם 3 טבלאות מקושרות
-
לכל טבלה שמייצגת מודעה יש:
טבלה של ערים - לפי הID של המודעה
טבלה של נקרא/לא נקרא - לפי הID של המודעה - כאן חוזרות גם המודעות שנקרא וגם אלו שלא אלא שהן מחולקות לנקראו ולא נקראו
טבלה של דירוג - לפי מספר הטלפון של המפרסםהשאילתה אמורה להוסיף את כל הנתונים מכל הטבלאות
אם מעבירים כפרמטר ערך לסינון (כמו עיר או אזור מסוימים, מספר טלפון מפרסם, מספר טלפון של מי ששומע את המודעות ועוד) אז המודעות צריכות להיות מסוננות (לדוגמא יופיעו רק מודעות מחיפה ולא מכל הארץ כמו אילו לא שלחו עיר לסינון)
השאלה איך נכון לעשות את זה.
במצב הנוכחי (הקוד שכתבתי) אם לא שלחו עיר כפרמטר, בכלל לא מחברים את הטבלה, מה שגורם לזה שחוזרות מודעות, אבל בלי ערים.
-
לכל טבלה שמייצגת מודעה יש:
טבלה של ערים - לפי הID של המודעה
טבלה של נקרא/לא נקרא - לפי הID של המודעה - כאן חוזרות גם המודעות שנקרא וגם אלו שלא אלא שהן מחולקות לנקראו ולא נקראו
טבלה של דירוג - לפי מספר הטלפון של המפרסםהשאילתה אמורה להוסיף את כל הנתונים מכל הטבלאות
אם מעבירים כפרמטר ערך לסינון (כמו עיר או אזור מסוימים, מספר טלפון מפרסם, מספר טלפון של מי ששומע את המודעות ועוד) אז המודעות צריכות להיות מסוננות (לדוגמא יופיעו רק מודעות מחיפה ולא מכל הארץ כמו אילו לא שלחו עיר לסינון)
השאלה איך נכון לעשות את זה.
במצב הנוכחי (הקוד שכתבתי) אם לא שלחו עיר כפרמטר, בכלל לא מחברים את הטבלה, מה שגורם לזה שחוזרות מודעות, אבל בלי ערים.
@eido הדילמה כאן היא קלאסית של סינון דינמי עם טבלאות מקושרות.
הטעות הנפוצה היא שמשנים את ה-JOIN לפי הפרמטרים שנשלחים. בפועל ה-JOIN צריך להיות קבוע, והסינון צריך להתבצע רק ב-WHERE.
כלל אצבע פשוט: JOIN משמש להבאת מידע, WHERE משמש לסינון מידע.
לכן נכון לחבר תמיד את כל הטבלאות הרלוונטיות (בדרך כלל עם LEFT JOIN), ואז לכתוב את תנאי הסינון
במצב כזה, אם לא נשלח פרמטר – אין סינון, אבל הנתונים מהטבלאות המקושרות עדיין חוזרים. אם כן נשלח פרמטר – מתבצע סינון כמצופה.
עוד משהו, אם יש טבלה שבה יש כמה רשומות לכל מודעה (למשל סטטוס נקרא/לא נקרא לפי מאזין), JOIN רגיל עלול לגרום לכפילויות של מודעות. במצבים כאלה עדיף לבצע את הסינון באמצעות EXISTS, תחפש על זה.
-
@eido הדילמה כאן היא קלאסית של סינון דינמי עם טבלאות מקושרות.
הטעות הנפוצה היא שמשנים את ה-JOIN לפי הפרמטרים שנשלחים. בפועל ה-JOIN צריך להיות קבוע, והסינון צריך להתבצע רק ב-WHERE.
כלל אצבע פשוט: JOIN משמש להבאת מידע, WHERE משמש לסינון מידע.
לכן נכון לחבר תמיד את כל הטבלאות הרלוונטיות (בדרך כלל עם LEFT JOIN), ואז לכתוב את תנאי הסינון
במצב כזה, אם לא נשלח פרמטר – אין סינון, אבל הנתונים מהטבלאות המקושרות עדיין חוזרים. אם כן נשלח פרמטר – מתבצע סינון כמצופה.
עוד משהו, אם יש טבלה שבה יש כמה רשומות לכל מודעה (למשל סטטוס נקרא/לא נקרא לפי מאזין), JOIN רגיל עלול לגרום לכפילויות של מודעות. במצבים כאלה עדיף לבצע את הסינון באמצעות EXISTS, תחפש על זה.
@אביי תודה רבה
עריכה:
השאלה שלי היא כי AI למיניהם טענו שכ"כ הרבה join מהוה עומס על השרת ומכביד סתם על כל תהליך השליפה, מה שא"כ אם שליפה מחלק מהטבלאות עושים ע"י בקשה שניה בקוד עצמו שאז אמנם זה לא שאילתא אחת מסודרת אבל זה לא מכריח את השרת לחבר טבלאות ולהשוות ביניהם. האם זו טענה נכונה וכזו כמות עדיף לא לחבר ולסנן (במקרה הצורך) בבת אחת או שזה שטויות ואין עם זה שום בעיה.אגב, מבחינת עבודה עם knex, זה עדיין טוב? אם הסינון לא מוגדר צמוד לטבלה איך מגדירים שהוא יהיה דוקא עליו ולא על טבלה אחרת? אני מרגיש שknex פחות טוב לדברים כאלה, הוא קצת מסבך את העסק בתנאים שקצת טיפה מורכבים.
-
א. השאלה לא עסקה בknex אלא בSQL
ב. השאלה היא בסיסית מאוד בשפת SQL
שוב אתה שואל בלי לדעת דברים בסיסיים מאוד,
ומשתמש בכלים (לראשונה בחיי שאני שומע על knex, אני מפתח בnodejs כמעט עשר שנים) כבקיא ורגיל ומגיע רק עם "שאלה קטנה" שנוגעת לליבת השימוש בטבלאות SQL.
מה אתה אמור לעשות? לא יודע, אבל תבין שהשאלה הראשונה מזמינה כל אחד שקצת למד SQL לענות, ובהודעה האחרונה אתה דופק את כלי מי שהיה טורח לענות, כי כמה שהתשובה יפה ונכונה היא לא בטוח רלוונטית עבור איזה כלי בשם knex. -
בקשר לknex, יש קשור הדוק בין העובדה שאתה לא יודע בכלל SQL (למרות שאתה עובד איתו לפחות כמה חודשים!)
לבין המחשבה שהוא לא תומך בכזה דבר (כמו לומר שיונדאי לא תומכת בלנסוע ברברס).
ביקשתי מקלוד דוגמה, והנה לפניך:knex('TableAds') .leftJoin('Readed', 'Readed.AdsId', 'TableAds.Id') .leftJoin('Cities', 'TableAds.CityId', 'Cities.Id') .where('Readed.Phone', phone) .where('Readed.IsReaded', 0) .select('*') -
א. השאלה לא עסקה בknex אלא בSQL
ב. השאלה היא בסיסית מאוד בשפת SQL
שוב אתה שואל בלי לדעת דברים בסיסיים מאוד,
ומשתמש בכלים (לראשונה בחיי שאני שומע על knex, אני מפתח בnodejs כמעט עשר שנים) כבקיא ורגיל ומגיע רק עם "שאלה קטנה" שנוגעת לליבת השימוש בטבלאות SQL.
מה אתה אמור לעשות? לא יודע, אבל תבין שהשאלה הראשונה מזמינה כל אחד שקצת למד SQL לענות, ובהודעה האחרונה אתה דופק את כלי מי שהיה טורח לענות, כי כמה שהתשובה יפה ונכונה היא לא בטוח רלוונטית עבור איזה כלי בשם knex.@dovid כתב בשליפת נתונים מטבלה עם 3 טבלאות מקושרות:
א. השאלה לא עסקה בknex אלא בSQL
השאלה עדיין עומדת על SQL שאלתי
כתב בשליפת נתונים מטבלה עם 3 טבלאות מקושרות:
השאלה איך נכון לעשות את זה.
וחידדתי
כתב בשליפת נתונים מטבלה עם 3 טבלאות מקושרות:
מבחינת עומס על השרת, AI למיניהם טענו שכ"כ הרבה join מהוה עומס על השרת ומכביד סתם על כל תהליך השליפה, מה שא"כ אם חלק מהם עושים ע"י בקשה שניה בקוד עצמו.
האמת, שאני רואה עכשיו שיצא לא מובן (בכל זאת 4 לפנות בוקר, קמתי רק להכין מטרנה או משהו...) אז אסביר כאן ואשנה גם שם.
הבעיה שלי היא לא המימוש, (כמו שכתבתי כמה וכמה פעמים, אני משתדל לא לבקש שיכתבו במקומי אלא איך נכון לעשות) אלא האם נכון לשלב 4 טבלאות ביחד... ניסיתי לחדד בהודעה השניה שהAI טענו שלא כדאי לעשות גם לזה JOIN כיון שזה מאוד מכביד על השרת, אלא עדיף למשוך את הערים בשאילתא נפרדת שלא תסבך את השרת, ושאלתי (לפחות התכוונתי) האם זה נכון? או שהם טועים ואין שום בעיה לחבר טבלאות.
@dovid כתב בשליפת נתונים מטבלה עם 3 טבלאות מקושרות:
לראשונה בחיי שאני שומע על knex
גם אני, @צדיק-תמים המליץ לי עליה במקום אחר ושיניתי את כל הפרויקט לספריה הזו, אני חושב שהיא מאוד שימושית.
@dovid כתב בשליפת נתונים מטבלה עם 3 טבלאות מקושרות:
אבל תבין שהשאלה הראשונה מזמינה כל אחד שקצת למד SQL לענות
מצוין, זה מה שאני צריך, כאמור אני צריך תאורטית, מה הדרך הנכונה, והאם הטענה ההיא נכונה או לא נכונה.
@dovid כתב בשליפת נתונים מטבלה עם 3 טבלאות מקושרות:
ובהודעה האחרונה אתה דופק את כלי מי שהיה טורח לענות, כי כמה שהתשובה יפה ונכונה היא לא בטוח רלוונטית עבור איזה כלי בשם knex
לא דופק אף אחד, מותר להגיד "הדרך של חיבור 4 טבלאות היא הנכונה כאן, לגבי knex - לא יודע" (אגב, בknex אפשר גם להכניס raw כך שאין בעיה, מכניסים שאילתת SQL כמו שהיא והכל טוב).
@dovid כתב בשליפת נתונים מטבלה עם 3 טבלאות מקושרות:
בין העובדה שאתה לא יודע בכלל SQL
מי קבע? למדתי את הנושא, הבנתי פחות או יותר אני יודע מה שאני צריך, נכון אני לא יודע עד הסוף, אבל את הבסיס אני בהחלט יודע. יש כאן לדוגמא מדריך חמוד ועוד מקומות. ובינינו SQL בסיסי כמו שאני צריך זה לא משהו מורכב כ"כ.
התנאים אצלי נראים יותר ככה:
let queryBuilder = knex("advertiser_ads as M").select("M.*"); queryBuilder.leftJoin("ratings as R", "R.rated", "M.phone"); queryBuilder.select(knex.raw("AVG(R.rating) as average_rating")); queryBuilder.groupBy("M.id"); עוד קוד, לא רלוונטי if (filters.phoneOfSearcher && isValidIsraeliPhone(filters.phoneOfSearcher)) { queryBuilder.select( knex.raw( `EXISTS ( SELECT 1 FROM advertiser_ads_read MK WHERE MK.id = M.id AND MK.phone = ? ) as was_read`, [filters.phoneOfSearcher] ) ); } עוד קוד לא רלוונטי queryBuilder.innerJoin("advertiser_cities as E", "E.id", "M.id"); queryBuilder.groupBy("M.id"); // חשוב למנוע כפילויות במודעה אם יש לה כמה ערים if (filters.cities && filters.cities.length > 0) { // המצב שבו המחפש הזין עיר/ערים ספציפיות queryBuilder.where(function() { // כלל 3: לשניהם יש עיר - בדיקת התאמה מדויקת לעיר this.whereIn("E.city", filters.cities) // כלל 2: למפרסם יש רק אזור - מפרסם שמשרת את כל האזור יעלה בתוצאות .orWhere(function() { this.where("E.area", filters.area).whereNull("E.city"); }) // כלל 1 (מתוקן ומאובטח): למפרסם יש "כל הארץ" (אזור ריק + עיר ריקה) - הוא יעלה בתוצאות תמיד .orWhere(function() { this.whereNull("E.area").whereNull("E.city"); }); }); } else { // המצב שבו המחפש הזין רק אזור (ללא עיר) queryBuilder.where(function() { // כלל 2: חיפוש לפי אזור (מכסה מפרסמים של כל האזור, וגם מפרסמים של עיר ספציפית באזור) this.where("E.area", filters.area) // כלל 1 (מתוקן ומאובטח): למפרסם יש "כל הארץ" (אזור ריק + עיר ריקה) - הוא יעלה בתוצאות תמיד .orWhere(function() { this.whereNull("E.area").whereNull("E.city"); }); }); }תנאים מורכבים שחושבו כמו שצריך.