שאלה ב mySQL

XiroX

New member
שאלה ב mySQL

איל אני מעביר נתונים בתוך mySQL משאילתה אחת לשניה? ניסיתי להשתמש במשתנים כמו שמצויין במניואל:
SET @a:= SELECT COUNT(*) AS num1 FROM `message_records` WHERE `storyid`=4 AND `userid`=5; SET @b:=SELECT `msgs` FROM `story_records` WHERE `id`= 4;​
אבל זה לא עבד. אז ניסיתי לעשות נוסח השוואתי בתוך שאילתה אחרת:
SELECT COUNT(*) AS num WHERE (SELECT COUNT(*) AS num1 FROM `message_records` WHERE `storyid`=4 AND `userid`=5) == (SELECT msgs FROM `story_records` WHERE `id`= 4)​
השאלה היא איך אני עושה סוג כזה של שאילתה, כי אני מעדיף להמנע משימוש ב php להצלבת נתונים. גם הפניה למניואל מתאים תעזור לי מאוד, כי לא מצאתי כשחיפשתי (אני כבר מחפש שבוע איך לעשות את זה)
 

lizard

New member
מה הכוונה מעביר נתונים?

לחפש מידע מטבלה אחת על סמך מידע בטבלה אחרת?
 

אמיר ט

New member
אוקי...

בוא תסביר עכשיו מה בדיוק אתה רוצה מהשאילתה הזאת, כלומר מה אתה רוצה שבסוף יצא. ואחרי זה תסביר קצת עם השדות, ובין איזה שדות יש קשר -> מה בדיוק אתה רוצה להשוות.
 

XiroX

New member
ok

קצת רקע. יש לי 2 טבלאות- אחת שיש בה מידע על כל הסיפורים (בהם שדה בשם msgs שבו כתוב כמה תגובות יש לכל סיפור) וטבלה שבה יש רשומה על כל תגובה שמשתמש נכנס (msgid) אליה, את המספר של המשתמש (userid) ומספר הסיפור(storyid). אני רוצה ליצור שאילתה שתצליב את המידע, ותחזיר לי כמה הודעות נשארו שהמתמש לא קרא עדיין. עד עכשיו אני עושה את זה ב- 2 שאילתות ומצליב אותן דרך PHP, אבל אז זה יוצא ממש לא יעיל. מה גם שאז כדי לעשות דפדוף, אני צריך לעשות עוד כל מני איכסות ובקיצור, לא יעיל ביותר. השאילתות שהצלבתי עד עכשיו:
SELECT COUNT(*) AS `num`,`storyid` FROM `message_records` GROUP BY `storyid`​
השאילתה הזאת מחזירה לי את כמה הודעות המשתמש קרא בכל סיפור, והשאילתה השניה:
SELECT `id`,`msgs`,`headline` FROM `story_records`​
שמחזירה לי רשימה של כל הסיפורים, כמה הודעות יש להם, והכותרת שלהם. עד עכשיו, אני מריץ פונקציה ב PHP שעושה הצלבה של הנתונים (לולאה כפולה כי צריך לסרוק את 2 המערכים, מה שאומר סיבוכיות ממש גבוהה), ומחזירה לי את התוצאה במערך חדש. כדי לעשות דפדוף, מכיוון שאני לא יכול לעשות הגבלה אמיתית של הסיפורים דרך המסד נתונים, אני צריך לעשות אחרי זה סינון מהמערך, דבר שיוצר עוד יותר אי יעילות. מקווה שיצאתי מובן. עד כמה שהבנתי, אני כן אמור להיות מסוגל לשמור נתונים משאילתה אחת לשניה, אני פשוט לא יודע איך. המשתנה שזהה בשניהם הוא id ו storyid
 

אמיר ט

New member
עוד קצת פרטים

עדיין לא הבנתי בדיוק מה אתה רוצה שהשאילתה תחזיר. תמיד תתחיל לבנות את השאילתה שלך בצורה הזאת, תרשום בדיוק מה אתה רוצה שהיא תחזיר, אז בוא נעשה את זה צעד צעד, תרשום את ההתחלה של השאילתה את מה שאתה רוצה שהיא תחזיר (מה בין ה SELECT ל FROM) אם לא הייתי מובן.
 

XiroX

New member
כך

SELECT (query2.msgs)- (query1.num) WHERE query1.id=query2.storyid​
זה הכי מובן שאני מצליח לעשות. כעיקרון, msgs הוא מספר ההודעות שיש בכל סיפור, וnum זה כמה שהמשתמש קרא כבר. אני רוצה לדעת כמה הוא לא קרא. הדרך לעשות את ההצלבה היא דרך id ו storyid כי שניהם הם בעצם אותו נתון, שהוא מספר הסיפור. אני רוצה לעשות שאילתה שתחזיר לי את הנתונים הנ"ל, כלפי כל הסיפורים בטבלה אחת. אם זה לא מובן עדיין, אני אביא קוד PHP שמדגים מה שאני רוצה לעשות יותר מאוחר (אבל הוא לא יעיל בטירוף).
 

lizard

New member
אני חושב שאולי זה יתן לך רעיונות

לא בטוח בכלל שזה יעבוד:
select [FIELDS] from [TABLES] where query1.id != query2.storyid​
יכול להיות שבמקום != צריך משהו אחר (<>) אבל בגדול לדעתי זה צריך לעבוד.
 

אמיר ט

New member
שמע, מה אני אגיד

אולי זה העייפות אחרי יום עבודה שלם אבל בחיי שאני לא מבין מה אתה עושה חוץ מלכתוב משפטי SQL לא הגיוניים בעליל. צא מהקטע של שני Query, זה מיותר. לדעתי חסר לך המון ידע ב SQL כדי ליישם את מה שאתה רוצה זה מצריך שילוב של השוואת שדות "אגרגטיבים" ושדות רגילים. בוא נפריד את הבעיה, אתה רוצה 2 דברים, אחד זה סה"כ ההודעות הקיימות. הדבר השני שאתה רוצה זה כמה נקראו. ועכשיו לדברים שאני לא ממש מבין : א. איך אתה יודע איזה תגובות כבר נקראו ? ב. אתה רוצה את מספר הרשומות שלא נקראו או הרשומות עצמן
 

XiroX

New member
כך

אני רוצה את מספר הרשומות. כך עשיתי אתזה ב PHP:
$read=SBF_Count_Total_Messages($user); /*SELECT COUNT(*) AS num1,storyid FROM `message_records` WHERE userid=$user ;*/ $total=SBF_Get_Stories_Info(); /*SELECT `msgs`,`id` FROM `story_records` WHERE*/ $k=0; for ($i=0;$i<sizeof($read);$i++) { for ($j=0;$j<sizeof($total);$j++) { if ($read[$i]['storyid']==$total[$j]['id']) { $numbers[$k][id]=$total[$j][id]; $numbers[$k][diff]=$total[$j][msgs]-$read[$i][num]; $k++; break; }; }; };​
 

XiroX

New member
2 תיקונים

1. הכוונה ל num לא num1 בקשר לאי התאמה. 2. בשאילתה השניה לא צריך WHERE, פשוט עשיתי העתקה/הדבקה ושכחתי למחוק
 

אמיר ט

New member
המ...

אולי תעשה משהו כזה :
SELECT COUNT(*) AS NUM,story_records.msgs FROM message_records,story_records WHERE story_records.id = message_records.storyid​
הכונה שלי כאן היא לשלוף את שני הנתונים בלי קשר לזה שאתה רוצה לחסר בניהם, את החיסור את יכול לעש/ות בPHP, קודם נראה שזה עובד. זה פחות או יותר מה שאתה צריך לעשות, ד"א יש דרכים הרבה יותר אלגנטיות לעשות מערכת שמראה לך רק מה שלא קראת...
 

XiroX

New member
טוב, תודה המון,

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

אמיר ט

New member
טיפה הרחבה...

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

XiroX

New member
לא יעיל בנקרה שלי

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