# پایگاه‌های داده > سایر پایگاه‌های داده > MySQL >  گرفتن محتوای از کوئری پیچیده

## eppagh

سلام

در 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

فکر کنم مشکل کوئریتون از OR باشه باید بین INNER JOIN ها از AND استفاده کنین. امتحان کنین اگه جواب نداد اطلاع بدین یه فکر دیگه میکنیم.

----------


## tabib_m

از ساب کوئری ها استفاده کن:

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

من دیروز روی مساله کار کردم و نتیجه آن اینکه : 
چون همزمان از بیش از یک فیلد در جدول 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

از دوست عزیزی که ساب کوئری را پیشنهاد کردند متشکرم . 
اما متاسفانه از سینتکس آن سر در نیاوردم .
یعنی نفهمیدم جدول مادر که 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

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

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

----------


## eppagh

این نمونه جدول مقالات و جدول آدم ها است : 

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

باید به ازای هر رابطه یک 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

با تشکر از oxygenws :

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

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

----------


## oxygenws

AS یک alias name برای اون ستون یا جدول می ذاره.
این کوئری رو توی برنامه های موجود (مثل query browser یا mysql client یا ...) اجرا کن تا بفهمی دقیقا چیه!

----------


## eppagh

کوئری که داد بودید را به 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

کوئری خودت رو بذار کنار، کلا بی خیال. ضمن اینکه ترجیح داره اون متون خطا رو کامل بخونی و خودت بفهمی چیه!

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

----------


## eppagh

oxygenws  دوست عزیز ؛ از راهنمایی شما بسیار سپاسگزارم . مساله به همین نحوی که شما راهنمایی کردید حل شد .

----------


## eppagh

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

----------

