PDA

View Full Version : گرفتن محتوای از کوئری پیچیده



eppagh
سه شنبه 27 شهریور 1386, 07:37 صبح
سلام

در MYSQL یک جدول دارم که اطلاعات مقالات را نگه می دارد . در این جدول در چهار فیلد id چهار مولف ( مولف اول ، مولف دوم ، مترجم ،‌ مصحح ) وجود دارد . اطلاعات این چهار id در یک جدول جداگانه است .
همچنین به همین شکل id دو منبع ( مرجع مطلب ) در جدول مقالات در دو فیلد ذخیره شده و جدول اطلاعات منابع جداست .

حالا می خواهم با یک کوئری بخش هایی از اطلاعات جدول مقالات را با مشخصات مولفین و منابع دریافت کنم .
این کوئری را برای آن نوشته ام :


SELECT papers.title_page , persons.first_name_person , persons.last_name_person , sources.reference_source , persons.last_name_person , subjects.phrase_subject
From papers
Inner Join persons ON papers.persons_author1_id = persons.id_person
OR papers.persons_author2_id = persons.id_person
Inner Join sources ON papers.source2_id = sources.id_source
OR papers.source1_id = sources.id_source
Inner Join paper_subjects ON papers.id_papers = paper_subjects.id_papers
Inner Join subjects ON paper_subjects.id_subject = subjects.id_subject
Where papers.id_papers = 9
LIMIT 0, 30 ;

انتظار داشتم اطلاعات فیلدهای درخواستی را در یک خط تحویل بدهد ، اما نتیجه در 12 خط ارسال می شود . یعنی لوپی که پاسخ کوئری بر می گردد ۱۲ بار می چرخد و ۱۲ خط پس می دهد که در هر خط اطلاعات مربوط به جدول مادر که مقالات باشد تکرار شده و اطلاعات اشخاص و منابع به صورت ترکیبی تکرار شده است . به این ترتیب باید از این ۱۲ خط اطلاعات مورد نیاز را دستچین کنم .

چطور می توانم با یک کوئری در یک خط ( یک چرخه لوپ ) پاسخ کل اطلاعات را دریافت کنم ؟:افسرده:

peyman1987
سه شنبه 27 شهریور 1386, 11:37 صبح
فکر کنم مشکل کوئریتون از OR باشه باید بین INNER JOIN ها از AND استفاده کنین. امتحان کنین اگه جواب نداد اطلاع بدین یه فکر دیگه میکنیم.

tabib_m
سه شنبه 27 شهریور 1386, 12:18 عصر
از ساب کوئری ها استفاده کن:


SELECT `id` , (select `field` from `table1` where `id`=`thisTable`.`id1`) as `value1` , (select `field` from `table2` where `id`=`thisTable`.`id2`) as `value2` , (select `field` from `table3` where `id`=`thisTable`.`id3`) as `value3` from `thisTable` where `id`='$theRecordId'


اگر نتونستی کوئری خودت رو توی این قالب جا بدی، بگو تا کمک کنم.

ممکنه با این روش یکم کوئریت طولانی بشه، ولی خوب به جاش جواب میده.
شاید به وسیله ی همین ساب کوئری ها راه های ساده تری هم باشه، ولی متأسفانه من بلد نیستم.

موفق باشید.

eppagh
چهارشنبه 28 شهریور 1386, 06:06 صبح
من دیروز روی مساله کار کردم و نتیجه آن اینکه :
چون همزمان از بیش از یک فیلد در جدول A ( حاوی id های جدول B ) به یک فید از جدول B ( فیلد id ) اشاره می شود ؛ ناچار باید در join از بیش از یک شرط استفاده کرد و آنها را با OR یا AND در کنار هم قرار داد .


Inner Join persons
ON papers.persons_author1_id = persons.id_person
OR papers.persons_author2_id = persons.id_person

اگر از AND استفاده شود فقط در صورتی جواب می دهد که هر مقادیر دو فیلد id ها در جدول یک مساوی باشد .
اگر از OR استفاده شود بیش از یک رکورد در جدول دو پاسخ می دهد .
در صورت اخیر جواب SQL به این صورت خواهد بود که به تعداد رکوردهای پاسخ در جدول B ، فیلدهای درخواست شده از جدول A را تکرار و هر بار در ادامه آن فیلدهای درخواست شده از جدول B را نمایش می دهد .
حال اگر تعداد جداول ثانوی بیش از یکی باشد ترکیبی از آنها را ارائه خواهد کرد . چنانکه در جدول مورد نظر من ۹ فیلد از جدول اول به id سه جدول متفاوت اشاره می کند و در نتیجه در ۱۲ چرخه لوپ پاسخ می دهد .

به نظر می رسد که این منطقی است با هر نوع join پاسخ به همین صورت است و به این نتیجه رسیدم که از فیدهای داده شده در چرخه های لوپ مقادیر مورد نیاز را دستچین کنم .

البته مورد استفاده از ساپ کوئری به چشمم خورد ولی رویش کار نکردم . با تشکر از دوست عزیزی که پیشنهاد کرده به نظر می رسد اول باید همین را بررسی کنم .

با این شرح کسی می تواند راهنمایی بیشتری بدهد ؟

eppagh
پنج شنبه 29 شهریور 1386, 05:30 صبح
از دوست عزیزی که ساب کوئری را پیشنهاد کردند متشکرم .
اما متاسفانه از سینتکس آن سر در نیاوردم .
یعنی نفهمیدم جدول مادر که id ها را دارد کدام است و جداولی که اطلاعات id ها را ذخیره کرده اند کدام هستند .
همچنین از این as `value2` ها سر در نیاوردم .

سوال اولیه این است که چون تعداد SELECT بیشتر پرفرنس را پایین می آورد ؛ این روش نوشتن ، چند SELECT حساب می شود یا یکی ؟


SELECT `id` , (select `field` from `table1` where `id`=`thisTable`.`id1`) as `value1` , (select `field` from `table2` where `id`=`thisTable`.`id2`) as `value2` , (select `field` from `table3` where `id`=`thisTable`.`id3`) as `value3` from `thisTable` where `id`='$theRecordId'

oxygenws
پنج شنبه 29 شهریور 1386, 05:59 صبح
اگر یک تصویر یا دیاگرام از ترتیب جداول و رابطه شون بکشی خیلی کمک می کنه، من که نفهمیدم چی به چی مربوطه.
(لطفا توضیح نده، مطمئن باش باز هم نمی فهمم :) )

ضمنا، تا جایی که میشه از subselect استفاده نشه (چون اکثر حالات رو میشه با join هم نوشت)

eppagh
پنج شنبه 29 شهریور 1386, 07:12 صبح
این نمونه جدول مقالات و جدول آدم ها است :


CREATE TABLE IF NOT EXISTS `papers` (
`id_papers` tinyint(3) NOT NULL auto_increment,
`title_page` tinytext character set utf8 collate utf8_unicode_ci NOT NULL,
`persons_author1_id` tinyint(3) NOT NULL default '0',
`persons_author2_id` tinyint(3) NOT NULL default '0',
`persons_translator_id` tinyint(3) NOT NULL default '0',
`persons_editor_id` tinyint(3) NOT NULL default '0',
`source1_id` tinyint(3) NOT NULL default '0',
`source2_id` tinyint(3) NOT NULL default '0',
PRIMARY KEY (`id_papers`),
FULLTEXT KEY `contents` (`contents`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci AUTO_INCREMENT=10 ;

CREATE TABLE IF NOT EXISTS `persons` (
`id_person` tinyint(3) NOT NULL auto_increment,
`first_name_person` tinytext character set utf8 collate utf8_unicode_ci NOT NULL,
`last_name_person` tinytext character set utf8 collate utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id_person`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci AUTO_INCREMENT=40 ;

صورت مساله این است که در یک خط مقادیر این فیلدها دریافت شود :
عنوان مقاله - نام خانوادگی مولف اول - نام کوچک مولف اول - نام خانوادگی مولف دوم - نام کوچک مولف دوم - نام خانوادگی مترجم - نام کوچک مترجم - نام خانوادگی مصحح - نام کوچک مصحح

ضمنا همانطور که مشاهده می شود مشابه همین مساله : ۳ موضوع و ۲ عنوان کتاب مورد ارجاع هم وجود دارد .

oxygenws
پنج شنبه 29 شهریور 1386, 13:33 عصر
باید به ازای هر رابطه یک join بزنید:

مثال:



SELECT pa1.first_name_person AS pa1_fname, pa1.last_name_person AS pa1_lname,
pa2.first_name_person AS pa2_fname, pa2.last_name_person AS pa2_lname,
pt.first_name_person AS pt_fname, pt.last_name_person AS pt_lname,
pe.first_name_person AS pe_fname, pe.last_name_person AS pe_lname
FROM papers
INNER JOIN persons AS pa1 ON papers.persons_author1_id = pa1.id
INNER JOIN persons AS pa2 ON papers.persons_author2_id = pa2.id
INNER JOIN persons AS pt ON papers.persons_translator_id = pt.id
INNER JOIN persons AS pe ON papers.persons_editor_id = pe.id

eppagh
جمعه 30 شهریور 1386, 14:13 عصر
با تشکر از oxygenws :

من از کارکرد AS سر در نیاورده ام .
در اینجا هم در قسمت SELECT هم در قسمت بعد متوجه نوع کارکرد آن نشدم .
اگر لطف کنید توضیح بدهید که بفهمم .

البته من راه گرفتن مقادیر فیلدهای مورد نیاز را از در حالت معمولی که از ۳ تا ۲۴ خط پس می دهد تقریبا پیدا کرده ام .
اما صدالبته اگر از یک خط بشود گرفت که خیلی عالی است :لبخند: و کلی خط از برنامه کم می شود .

oxygenws
جمعه 30 شهریور 1386, 14:57 عصر
AS یک alias name برای اون ستون یا جدول می ذاره.
این کوئری رو توی برنامه های موجود (مثل query browser یا mysql client یا ...) اجرا کن تا بفهمی دقیقا چیه!

eppagh
شنبه 31 شهریور 1386, 19:52 عصر
کوئری که داد بودید را به MYSQL دادم و این نتیجه اش :


Error
SQL query:

SELECT
pa1.first_name_person AS pa1_fname,
pa1.last_name_person AS pa1_lname,
pa2.first_name_person AS pa2_fname,
pa2.last_name_person AS pa2_lname,
pt.first_name_person AS pt_fname,
pt.last_name_person AS pt_lname,
pe.first_name_person AS pe_fname,
pe.last_name_person AS pe_lname
FROM papers
INNER JOIN persons AS pa1 ON papers.persons_author1_id = pa1.id
INNER JOIN persons AS pa2 ON papers.persons_author2_id = pa2.id
INNER JOIN persons AS pt ON papers.persons_translator_id = pt.id
INNER JOIN persons AS pe ON papers.persons_editor_id = pe.id

MySQL said: Documentation
#1054 - Unknown column 'pa1.id' in 'on clause'

این کوئری را هم خودم نوشتم و نتیجه :


Error
SQL query:

SELECT papers.title_page,
persons.first_name_person AS author1_fname,
persons.last_name_person AS author1_lname
persons.first_name_person AS author2_fname,
persons.last_name_person AS author2_lname
persons.first_name_person AS translator_fname,
persons.last_name_person AS translator_lname
persons.first_name_person AS editor_fname,
persons.last_name_person AS editor_lname
FROM papers
INNER JOIN persons AS author1 ON papers.persons_author1_id = author1.id
INNER JOIN persons AS author2 ON papers.persons_author2_id = author2.id
INNER JOIN persons AS translator ON papers.persons_translator_id = translator.id
INNER JOIN persons AS editor ON papers.persons_editor_id = editor.id

MySQL said: Documentation
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'persons.first_name_person AS author2_fname , persons.last_name_person As author2' at line 1

اگر درست فهمیده باشم که با نام مستعار قرار بوده چند join به یک جدول گرفته شود ، به نظر می رسد MYSQL گول نخورده !:افسرده:

نظرتون چیه ؟

oxygenws
شنبه 31 شهریور 1386, 21:50 عصر
کوئری خودت رو بذار کنار، کلا بی خیال. ضمن اینکه ترجیح داره اون متون خطا رو کامل بخونی و خودت بفهمی چیه!

هر جا نوشته بودم id. (به نقطه توجه کن!!)، تبدیلش کن به id_person. (باز هم به نقطه دقت کن!!!!)

eppagh
دوشنبه 02 مهر 1386, 05:40 صبح
oxygenws دوست عزیز ؛ از راهنمایی شما بسیار سپاسگزارم . مساله به همین نحوی که شما راهنمایی کردید حل شد .

eppagh
سه شنبه 03 مهر 1386, 06:06 صبح
SELECT
author1.pre_title AS author1_pre_title,
author1.first_name_person AS author1_fname,
author1.last_name_person AS author1_lname,
author1.last_title AS author1_pre_title,
author1.link_person AS author1_pre_title,

author2.pre_title AS author2_pre_title,
author2.first_name_person AS author2_fname,
author2.last_name_person AS autho2_lname,
author2.last_title AS author2_pre_title,
author2.link_person AS autho2_pre_title,

source1.reference_source AS reference_source1,
source1.link_source AS link_source_source1,

source2.reference_source AS reference_source2,
source2.link_source AS link_source_source2,

FROM papers

INNER JOIN persons AS author1 ON papers.persons_author1_id = author1.id_person
INNER JOIN persons AS author2 ON papers.persons_author2_id = author2.id_person
INNER JOIN sources AS source1 ON papers.source1_id = source1.id_source
INNER JOIN sources AS source2 ON papers.source2_id = source2.id_source

WHERE papers.id_papers =3