איך עושים JOIN?
-
אני מקווה שהשאלה תהיה מובנת.
יש לי טבלהinfo
עם עמודות של מספרי טלפון,שמות,קבוצות
וטבלה שניהpoints
עם עמודה של ניקוד , מספר טלפון,וקבוצה.אני רוצה לקבל את כל הרשימה של הניקוד של קבוצה מסויימת עם השמות שלהם
יש לציין שיש מספרי טלפון שמופיעים בשני קבוצות בinfo
ואני רוצה רק את השם שמופיע בקבוצה הנוכחית.בשביל לקבל את הרשימה בלי שמות עשיתי כך
SELECT user ,points FROM points WHERE grup=123
עכשיו אני מנסה לעשות JOIN ולא מצליח
קודם כל השאילתא:
SELECT user ,points FROM points JOIN info ON info.user=points.user ;
מחזירהERROR 1052 (23000): Column 'user' in field list is ambiguous
ואם אני מוריד את user
SELECTpoints FROM points WHERE grup=123
אז הבקשת נתקעת ואני לא מקבל תגובה בכלל, עד שאני מקיש Ctrl-C
ומקבל :Ctrl-C -- sending "KILL QUERY 87418" to server ... Ctrl-C -- query aborted. ERROR 1317 (70100): Query execution was interrupted
אז כנראה פיספסתי משהו באיך עושים JOIN.
-
@nigun אמר באיך עושים JOIN?:
קודם כל השאילתא:
SELECT user ,points FROM points JOIN info ON info.user=points.user ;
מחזירה
ERROR 1052 (23000): Column 'user' in field list is ambiguousצריך לכתוב
points.user
אוinfo.user
אחרת הוא לא יודע מאיפה לקחת את העמודהuser
(למרות שעם קצת מחשבה הוא היה יכול להגיע למסקנה שלפי תנאי ה-JOIN יש לשניהם אותו ערך, אבל כנראה הוא לא מוכן להשקיע קצת מחשבה...) -
CREATE TABLE `userinfo` ( `id` INT(10) NOT NULL AUTO_INCREMENT, `grup` INT(11) NULL DEFAULT NULL, `user` VARCHAR(14) NULL DEFAULT NULL, `nameText` TEXT NULL DEFAULT NULL, `note` TEXT NULL DEFAULT NULL, PRIMARY KEY (`id`) CREATE TABLE `points` ( `id` INT(10) NOT NULL AUTO_INCREMENT, `grup` INT(11) NULL DEFAULT NULL, `user` VARCHAR(20) NULL DEFAULT NULL, `questionId` INT(11) NULL DEFAULT NULL, `points` INT(11) NULL DEFAULT NULL, `time` INT(64) NULL DEFAULT NULL, `answerId` INT(11) NULL DEFAULT NULL, PRIMARY KEY (`id`))
-
@nigun ייתכן שסוג הנתונים של מחרוזת בשילוב עם מספר הרשומות הגדול יוצר מעמסה.
ראשית, הייתי מנסה לבצע את הJoin על קבוצה קטנה, למשל ה-1000 הראשונים מכל טבלה ולראות אם נתקע:SELECT P.user, P.points FROM (SELECT TOP 1000 * FROM points) AS P JOIN (SELECT TOP 1000 * FROM userinfo) AS I ON P.user=I.user ;
בטבלת points יש 371574 שורות
בטבלת info יש 29542 שורות.לפי הנתונים, מספר הרשומות האפשריות בJoin הוא 371K * 29K = 10,759,000,000!
לפי סדר הריצה כנראה הDB מבצע JOIN ואח"כ מסנן.
אם אתה צריך רק קבוצה מסויימת, תסנן את שתי הטבלאות לפני הJOINעריכה: בהתבוננות שניה, עדיין לא הבנתי מדוע אתה מבצע JOIN אך לא מציג כלום מטבלת userinfo
-
@nigun אמר באיך עושים JOIN?:
מה ההבדל בין ...
לכאורה אין הבדל:
SELECT points.user, points.points FROM points JOIN info ON info.user=points.user
לבין (אם נוריד את ה TOP\LIMIT)
SELECT points.user, points.points FROM points JOIN userinfo ON points.user=userinfo.user;
אינני יודע, אך אולי ב MYSQL הסדר של ה ON משנה וצריך לרשום:
ON points.user=info.user
ולא
ON info.user=points.user
-
@nigun אמר באיך עושים JOIN?:
אולי אני ישאיר את זה לחצי שעה
אני עדיין מציע לך לבצע סינון WHERE לפי הקבוצה לפני הJOIN, ולהרוויח את הזמן הזה:
SELECT P.user, P.points,I.nameText FROM (SELECT * FROM points WHERE points.grup=123) AS P JOIN (SELECT * FROM userinfo WHERE userinfo.grup=123) AS I ON P.user=I.user;
-
@OdedDvir אמר באיך עושים JOIN?:
@nigun אמר באיך עושים JOIN?:
אולי אני ישאיר את זה לחצי שעה
אני עדיין מציע לך לבצע סינון WHERE לפי הקבוצה לפני הJOIN, ולהרוויח את הזמן הזה:
SELECT P.user, P.points,I.nameText FROM (SELECT * FROM points WHERE points.grup=123) AS P JOIN (SELECT * FROM userinfo WHERE userinfo.grup=123) AS I ON P.user=I.user;
יפה
עכשיו זה ירד ל0.23 שניות. -
@nigun אמר באיך עושים JOIN?:
מעניין מה ההבדל?
כתבתי למעלה, שמשום מה סדר הריצה של המסד נתונים שלך היה קודם כל לבצע JOIN (מה שיצר כנראה מליוני רשומות) ורק אח"כ סינון ב-WHERE.
תוסיף את העניין שמדובר ב-JOIN של מחרוזות שגם הוא איטי בהרבה מJOIN של מספרים - וקיבלת חצי שעה של תעסוקה למעבד...@dovid אמר באיך עושים JOIN?:
בדרך כלל המסד נתונים לבד בוחר לבצע סינון לפני הJOIN אם יש לו אינדיקציות ברורות שזה שווה.
אולי עדיף לא להשאיר את הדבר בידיים של הDB איפה שאפשר בקלות לקבוע את הסדר כדלעיל?