آگهی
article

استفاده از JOIN و ساخت پرس و جوی ترکیبی در MySQL

mysql-join

مطالبی که تا این لحظه از بخش آموزش مقدماتی MySQL فرا گرفته ایم معمولا برای حالت های متداول و کار با جداول به صورت مجزا کافی خواهند بود، اما در برنامه نویسی های پیشرفته تر و در طراحی ساختار برنامه های پیچیده نیاز به نوشتن پرس و جوهای ترکیبی و برقراری تعامل بیشتر بین جداول موجود در دیتابیس است، این نیاز سبب شده که قابلیت دیگری تحت عنوان JOIN (و مشتقات آن) به دستورات MySQL اضافه شود که به کمک آن می توان پرس و جوهای ترکیبی نوشت و بین جداول مختلف ارتباط برقرار کرد، در ادامه در مورد آن بیشتر خواهیم گفت.

ساخت جداول فرضی با دستور CREATE


برای درک بهتر نحوه عملکرد دستور JOIN پیش از هر چیز لازم است که چند جدول و ستون فرضی با مقادیری از پیش تعریف شده بسازیم که در زیر پرس و جوی آن را ملاحظه می کنید.
نکته: پیش از اجرای کدهای زیر باید از طریق برنامه phpMyAdmin دیتابیسی با نام فرضی test بسازید، دقت کنید که Collation دیتابیس بر روی utf8_persian_ci تنظیم شده باشد.
<?php
$con = mysql_connect("localhost","root","");
if (!$con){
    die('اتصال برقرار نشد: ' . mysql_error());
}
mysql_select_db("test", $con);
mysql_query("SET NAMES 'utf8'");

mysql_query("CREATE TABLE tbl_1(
id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY(id),
name VARCHAR(255),
skill VARCHAR(255)) ENGINE=MyISAM "
)
or die(mysql_error());

mysql_query("ALTER TABLE tbl_1
DEFAULT CHARACTER SET utf8
COLLATE utf8_persian_ci;"
)
or die(mysql_error());

mysql_query("CREATE TABLE tbl_2(
id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY(id),
language VARCHAR(255),
count VARCHAR(255)) ENGINE=MyISAM "
)
or die(mysql_error());

mysql_query("ALTER TABLE tbl_2
DEFAULT CHARACTER SET utf8
COLLATE utf8_persian_ci;"
)
or die(mysql_error());

echo "جدول با موفقیت ساخته شد!<br>";

//اطلاعات اولیه به صورت آرایه
$name_skill = array('علی' => 'HTML', 'ساسان' => 'PHP', 'پدرام' => 'Ajax');
$language_count = array('HTML' => 9, 'PHP' => 3, 'Ajax' => 6);

//ذخیره در دیتابیس
foreach($name_skill as $key => $value){
    mysql_query("INSERT INTO tbl_1 (name, skill) VALUES('$key', '$value')")
    or die(mysql_error());
}
foreach($language_count as $key => $value){
    mysql_query("INSERT INTO tbl_2 (language, count) VALUES('$key', '$value')")
    or die(mysql_error());
}

echo "اطلاعات با موفقیت افزوده شد!<br>";

mysql_close($con);
?>
پرس و جوی بالا دو جدول با مقادیری از پیش تعریف شده ایجاد می کند، در جدول نخست لیست کاربران به همراه مهارت برنامه نویسی آنها به صورت زیر قرار دارد.
id     name     skill
1     علی       HTML
2     ساسان     PHP
3     پدرام     Ajax
در جدول دوم عنوان هر زبان برنامه نویسی و به فرض تعداد برنامه نویس موجود و مسلط به آن زبان درج شده.
id     language      count
1       HTML           9
2       PHP            3
3       Ajax           6
همان طور که ملاحظه می کنید بین دو جدول در ستون های skill و language ارتباطی متقابل وجود دارد (هر دو ستون عناوین مربوط به زبان های برنامه نویسی را در خود دارند)، بنابراین به فرض اگر بخواهیم مسابقه ای بین افراد هم مهارت برگزار کنیم و نیاز به محاسبه تعداد رقبای اسامی موجود در جدول اول باشد، به ناچار باید در پرس و جوی خود هم از اصلاعات جدول اول (اسامی و مهارت آنها) و هم از اطلاعات جدول دوم (مهارت و تعداد شرکت کننده) استفاده کنیم، هرچند این کار با نوشتن دو پرس و جو نیز امکانپذیر است، اما حرفه ای تر آن است که به کمک JOIN و مشتقات آن (INNER JOIN، LEFT JOIN، RIGHT JOIN، OUTER JOIN) یک پرس و جوی ترکیبی نوشته و به هدف خود برسیم، بدین ترتیب می توان نوشت:
$resutl = mysql_query("SELECT tbl_1.name, tbl_2.count FROM tbl_1 INNER JOIN tbl_2 ON tbl_1.skill = tbl_2.language")
or die(mysql_error());
while($row = mysql_fetch_array($resutl)){
    echo $row['name']. ' : ' .$row['count']. '<br>';    
}
که خروجی دستور بالا به صورت نمونه زیر خواهد بود.
علی : 9
ساسان : 3
پدرام : 6
نکته: برای تعریف شرط در هنگام استفاده از دستور JOIN (و مشتقات آن)، از عبارت ON استفاده می شود.
برای آشنایی بیشتر با JOIN و مشتقات آن، در ادامه به صورت موردی این دستور را بررسی می کنیم.

حالت INNER JOIN


حالت اول از مشتقات دستور JOIN به صورت INNER JOIN می باشد، در این حالت می توان به مواردی مشترک از هر دو جدول دسترسی داشت، نتیجه پرس و جو شامل برخی موارد از جدول اول به همراه برخی موارد دیگر از جدول دوم (بر اساس شرط تعیین شده) خواهد بود، مثال:
SELECT tbl_1.skill, tbl_2.count FROM tbl_1 INNER JOIN tbl_2 ON tbl_1.skill = tbl_2.language
خروجی این حالت به صورت زیر خواهد بود.
skill     count
HTML       9
PHP        3
Ajax       6
ملاحظه می کنید که با اجرای پرس و جوی بالا ردیف های زیر از جدول اول:
HTML
PHP
Ajax
و ردیف های زیر از جدول دوم به عنوان خروجی برگردانده می شوند:
9
3
6

حالت LEFT JOIN


نوع دیگر از مشتقات دستور JOIN به صورت LEFT JOIN است که در این حالت تمام ردیف های جدول اول صرف نظر از شرط تعیین شده به همراه ردیف های جدول دوم (بر اساس شرط تعیین شده) به عنوان خروجی برگردانده می شوند، مثال:
SELECT tbl_1.skill, tbl_2.count FROM tbl_1 LEFT JOIN tbl_2 ON tbl_1.id = tbl_2.count
خروجی پرس و جوی بالا به صورت زیر خواهد بود.
skill     count
HTML      NULL
PHP       NULL
Ajax       3
نکته: ردیف هایی که در جدول دوم بر اساس شرط تعریف شده انتخاب نشوند، با مقدار NULL برگردانده می شوند.

حالت RIGHT JOIN


مشابه حالت LEFT JOIN، حالت RIGHT JOIN است که در این صورت ردیف ها از جدول دوم صرف نظر از شرط تعیین شده انتخاب و ردیف های جدول اول بر اساس شرط انتخاب می شوند، مثال:
SELECT tbl_1.skill, tbl_2.count FROM tbl_1 RIGHT JOIN tbl_2 ON tbl_1.id = tbl_2.count
خروجی پرس و جوی بالا به صورت زیر خواهد بود.
skill     count
NULL        9
Ajax        3
NULL        6

حالت OUTER JOIN


حالت آخر از مشتقات JOIN به صورت OUTER JOIN یا FULL JOIN است که در این صورت می توان دو پرس و جوی مبتنی بر JOIN را با عبارت کلیدی UNION (اجتماع) به هم مرتبط نمود، مثال:
SELECT tbl_1.skill, tbl_2.count FROM tbl_1 LEFT JOIN tbl_2 ON tbl_1.id = tbl_2.count UNION SELECT tbl_1.skill, tbl_2.count FROM tbl_1 RIGHT JOIN tbl_2 ON tbl_1.id = tbl_2.count
نتیجه پرس و جوی بالا به صورت زیر خواهد بود.
skill     count
HTML      NULL
PHP       NULL
Ajax       3 
NULL       9
NULL       6
sectionدسته بندی: آموزش مقدماتی » MySQL
related مطالب بیشتر:
» حذف مقادیر از MySQL با دستور DELETE
» نحوه ذخیره کردن اطلاعات با دستور INSERT در MySQL
» به روز رسانی ردیف ها در MySQL با UPDATE
» آموزش MySQL، سیستم مدیریت پایگاه داده
» ساخت دیتابیس، جدول و ستون با دستور CREATE در MySQL
commentنظرات (۳۷ یادداشت برای این مطلب ارسال شده است)
more یادداشت های جدید بر اساس تاریخ ارسال در انتهای یادداشت های موجود نمایش داده می شوند.
نویسنده: امیرحسین
۰۰:۱۶ ۱۳۹۶/۰۲/۲۱
سلام استاد عزیز
یه سوال داشتم اگر جواب بدید خیلی لطف میکنید
من میخوام از دستور where در join ها هم استفاده کنم ترتیبشون چگونه است
SELECT tbl_attr.title,tbl_product_attr.value FROM tbl_attr LEFT JOIN tbl_product_attr ON tbl_attr.id = tbl_product_attr.idattr
SELECT tbl_attr.title,tbl_product_attr.value FROM tbl_attr @where LEFT JOIN tbl_product_attr ON tbl_attr.id = tbl_product_attr.idattr
SELECT tbl_attr.title,tbl_product_attr.value FROM tbl_attr LEFT JOIN tbl_product_attr @where ON tbl_attr.id = tbl_product_attr.idattr
SELECT tbl_attr.title,tbl_product_attr.value FROM tbl_attr LEFT JOIN tbl_product_attr ON tbl_attr.id = tbl_product_attr.idattr @WHERE
به این WHERE ها دقت کنید که از دستی @ گذاشتم که رنگش آبی بشه مشخص بشه در کجا میتوانم استفاده کنم ایا بعد از FROM یا بعد از JOIN مربوطه یا بعد از ON یا قبلش ایا سه بار میشه از WHERE استفاده کرد یعنی هم برای FROM هم برای JOIN و ترتیبشون رو هم ذکر کنید که مثلا یه دستور JOIN دارم ترتیب های where,on,having را ذکر کنید.
پاسخ: 
پارامتر WHERE باید در پایان پرس و جو بیاید، اگر نیاز به اعمال شرط های بیشتر باشد، در کنار WHERE از AND و OR استفاده کنید، HAVING برای مواردی است که از GROUP BY استفاده می کنیم و مانند WHERE باید در پایان پرس و جو بیاید، مثال:
SELECT tbl_1.id, tbl_1.name, tbl_2.age 
FROM tbl_1
LEFT JOIN tbl_2 ON tbl_1.id = tbl_2.id
GROUP BY tbl_1.id
HAVING tbl_2.age > 20

SELECT tbl_1.id, tbl_1.name, tbl_2.age
FROM tbl_1
LEFT JOIN tbl_2 ON tbl_1.id = tbl_2.id
WHERE tbl_2.age > 20
AND tbl_2.age != 55
LIMIT 0 , 30
نویسنده: واحد
۰۹:۳۵ ۱۳۹۶/۰۳/۲۱
سلام
من سه جدول دارم که یکی برای ذخیره خودرو یکی برای ذخیره املاک و دیگری برای ذخیره لوازم الکتریکی دارم. می خواهم اطلاعات را از این سه جدول بگیرم و بر اساس تاریخ درج مرتب کنم. لطفا من را راهنمایی کنید.
خیلی ممنون
پاسخ: 
در حالت کلی و اگر دریافت تمام اطلاعات مد نظر باشد باید از الگوی نمونه کد زیر پیروی کنید:
SELECT col_item, col_date
FROM table_1
UNION ALL
SELECT col_item, col_date
FROM table_2
UNION ALL
SELECT col_item, col_date
FROM table_3
ORDER BY col_date DESC
نویسنده: نوید
۱۲:۰۰ ۱۳۹۶/۰۶/۰۵
سلام
میخواستم بدونم میشه ما بین 3 الی 4 تا جدول هم join کرد؟ اگر میشه به چه شکلی و سینتکسی
ممنونم
پاسخ: 
لطفا به این آدرس مراجعه کنید:
http://www.blokeish.com/2011/08/join-sql-multiple-3-4-tables-mysql/
نویسنده: رحیمی
۱۳:۵۶ ۱۳۹۸/۱۲/۲۶
با سلام
ضمن تشکر از آموزش بسیار خوب شما
لطفا بفرمایید وقتی دو جدول با هم لفت جوین می شوند همانطور که فرمودید بدلیل لفت جوین شدن امکان وجود سطر خالی در جدول دوم وجود دارد، حالا اگر خواسته باشیم بدون اینکه دو جدول را انییر جوین کنیم با یک شرط سطرهای خالی جدول دوم را انتخاب کنیم چه دستوری باید بکار ببریم
پاسخ: 
لطفا سوال را به همراه نمونه ساختار دو جدول فرضی مطرح و مشخص کنید نتیچه مد نظرتان به چه نحوی باید باشد، با توجه به توضیحات اگر هدف صرفا انتخاب مواردی است که ستون جدول دوم به صورت NULL است نمونه پرس و جوی زیر کاربرد دارد:
SELECT tbl_1.num AS row_1, tbl_2.num AS row_2 FROM tbl_1 LEFT JOIN tbl_2 ON tbl_1.num = tbl_2.num WHERE tbl_2.num IS NULL
نکته: با توجه به هدفتان ممکن است دستور LEFT JOIN گزینه مناسبی نباشد و با دستورات دیگری بتوانیم به هدف دست پیدا کنیم که با تعیین دقیق ساختار دیتابیس و نتیجه مورد انتظار شکل پرس و جوی لازم مشخص می شود.
نویسنده: hasti
۲۰:۰۵ ۱۳۹۹/۰۲/۱۶
سلام . وقت بخیر . میشه مثالی بزنید که right over join برابر با inner join (داخلی) بشه . /با order و customer/
و یدونم left over join برابر با inner join (داخلی) بشه
خیییلی ممنون .
پاسخ: 
برابر شدن نتیجه پرس و جوها در حالت JOIN به ساختار دیتابیس و مقادیر ردیف ها بستگی دارد، همچنین معمولا این در شرایطی است که پارامتر WHERE در پرس و جو در نظر گرفته شود، به فرض:
SELECT tbl_1.customer, tbl_2.order FROM tbl_1 INNER JOIN tbl_2 ON tbl_1.c_id = tbl_2.c_id WHERE tbl_1.cash > 100
البته این صرفا مثال است، در صورت تمایل ساختار نمونه دیتابیستان را به صورت فرمت sql به آدرس ایمیل ما (موجود در بخش تماس) به همراه توضیحات و خروجی مورد انتظار ارسال کنید تا بررسی گردد.
نویسنده: امیر
۰۵:۲۹ ۱۳۹۹/۰۲/۱۹
با سلام، خدمت دوستان عزیز دو جدول به نام‌های Messages و Comments موجود هستند.
در جدول Comments فیلدی به نام IDElement وجود دارد که ID پیامی که کامنت برای آن ثبت شده ذخیره می‌شود (مشخص می‌کند کامنت جاری مربوط به کدام رکورد از جدول Message است). همچنین در هر دو جدول فیلدهایی با نام IsShow وجود دارند که بیانگر نمایش و عدم نمایش هستند با مقدار True و False جدول Comments یک فیلد Action هم دارد که مشخص میکند این کامنت مربوط به پیام‌ها هستند (Messages) یا خبرها (News) که در آن یک رشته ثابت "Post" یا "News" ذخیره می‌شود.
حال میخواهم کوئری SQL بنویسم که در یک جدول تمام IDMessage ها و تعداد کامنت‌های مربوط به آن‌ها را برگرداند. (اگر پیامی کامنت نداشت باید مقدار فیلد تعداد کامنت صفر درنظر گرفته شود و اینکه کامنت هایی که IsShow آن‌ها False هستند درنظر گرفته نشوند..)
با تشکر
پاسخ: 
برای انتخاب از جدول اول در حالت اشتراک و عدم اشتراک ستون ها باید پرس و جوی ترکیبی بنویسیم، می توانید از نمونه پرس و جوی زیر الگوبرداری کنید:
(SELECT a.id AS 'message_id', COUNT(b.IdElement) AS 'comment_count' FROM messages a LEFT JOIN comments b ON a.id = b.IdElement WHERE b.IsShow = 'True' GROUP BY a.id)
UNION
(SELECT id AS 'message_id', 0 AS 'comment_count' FROM messages WHERE id NOT IN (SELECT IdElement FROM comments))
نویسنده: میثم
۲۳:۵۸ ۱۳۹۹/۰۵/۰۱
سلام
من برای دریافت چند تا اطلاعات از جداول سایتم مجبور شدم دستور زیر رو اجرا کنم.
هر کدام از جداول حدود ۱.۰۰۰.۰۰۰ رکورد دارن.
$res=mysql_query("Select * From tba INNER JOIN tbb ON tba.xxx = tbb.yy Where tba.zzz = '2' and find_in_set(3,vvv) Order By tba.time DESC Limit 50");
به نظرتون دستور بالا بهینه هست و آیا راهی هست که بشه سرعت اجرای دستور رو بالاتر برد؟
راستی من به تمام ستون های هر دو تا جدول برای نمایش اطلاعات نیاز دارم.
پاسخ: 
در صورتی که از ایندکس گذاری (Indexing) بر روی ستون های درگیر در تصمیم گیری MySQL در انتخاب نتایج (به فرض ستون های tba.xxx، tbb.yy، tba.zzz، tba.time) استفاده کرده باشید پرس و جو بهینه است، نکته دوم اینکه برای کدهای جدید از اکستنشن MySQLi استفاده کنید (آموزش فعلی قدیمی است و به زودی ویرایش می شود).
more لطفا پیش از ارسال یادداشت نکات زیر را مد نظر داشته باشید:
- مواردی که به کلی خارج از موضوع این مطلب هستند را در فرم منوی "تماس با ما" مطرح و پاسخ را از طریق ایمیل دریافت کنید.
- به سوالات کلی، مبهم، غیرضروری و مشکلاتی که تلاشی برای رفع آن نکرده باشید پاسخ کوتاه و مختصر داده خواهد شد!
- کدها و اسکریپت های طولانی را ترجیحا در یک صفحه وب آنلاین قرار دهید تا امکان تست و بررسی وجود داشته باشد.
- تمام یادداشت ها بررسی و برای هر کاربر زمان مشخصی جهت پاسخگویی در نظر گرفته می شود، لطفا از طرح سوالات متعدد در بازه زمانی کوتاه خودداری کنید.





3 × 2
 refresh
آخرین دیدگاه ها
more برای دسترسی سریع به یادداشت مربوطه می توانید از لینک مطلب در کادر زیر استفاده کنید.
form عاطفه مرادی
در:
سلام. من تازه یادگیری html رو شروع کردم و برای وبسایتمون برروی کنترل پنل html می نویسم. از طراح وبسایت خواستم که دسترسی جاوا را...
۱۳۹۹/۰۵/۱۹

form Amir Rahimi
در:
سلام و خسته نباشید من یک سوالی داشتم که مربوط به این بحث نیست سوال من اینه که یه کد یا . ....
۱۳۹۹/۰۵/۱۸

form محمد
در:
سلام اگر بخواهیم هدر سایت در گوشی های موبایل مخفی بشه از چه کدی باید استفاده کرد. کد زیر کلا مخفی میکنه در صورتیکه من...
۱۳۹۹/۰۵/۱۸

form shayan
در:
با سلام وقت به خیر من میخوام تو یه زبانه ای که در واقع متن قرار دادم لینک اسکرول بالا در حده پیکسل...
۱۳۹۹/۰۵/۱۷

form mahtab
در:
ببخشید اگه انتی ویروس رو غیرفعال کنیم برای باز کردن وب که باز نمیشه دوباره میتونیم آنتی ویروس رو فعال کنیم ؟؟ ...
۱۳۹۹/۰۵/۱۵

form امیرمحمد خلیلی
در:
ببخشید چجوری میتونم یه عکس از کاربر بگیرم و نمایشش بدم؟
۱۳۹۹/۰۵/۱۵

form elias
در:
خسته نباشید کاری که گفته بودید انجام دادم ولی رفرش می کنم همه لینک ها بر می گرده مثل اول می شه
۱۳۹۹/۰۵/۱۴

form سفی
در:
سلام و خسته نباشید من فایل آموزش html مقدماتی رو دیدم اما وقتی روی index.html کلیک راست کردم این گزینه ++edit..c رو ندیدم چه برنامه...
۱۳۹۹/۰۵/۱۰

form dnmax
در:
ببخشید ما اگه بخواهیم در وبلاگ مان به بقیه کدهای جاوا بدهیم وقتی کد رو پست میکنیم کد نشان داده نمیشود مثلا کد پخش آهنگ...
۱۳۹۹/۰۵/۰۹

form علیرضا
در:
سلام خیلی ممنون بابت مطالب مفیدتون عاالی بودن ان شالله همیشه موفق باشین.
۱۳۹۹/۰۵/۰۹

form محمد معین محب
در:
سلام میشه برای من یک اچ تی ام ال با بسازید . ممنون میشم
۱۳۹۹/۰۵/۰۸

form مهدی
در:
سلام و خسته نباشید یه مشکلی دارم که فکر کنم فقط وبگو میتونه کمک کنه سرور دانلود دارم و از اسکریپت دانلود vip...
۱۳۹۹/۰۵/۰۸

form neda
در:
با سلام من سایتی زدم از نظر ریسپانسیو هم اکی هست. فقط ارتفاعش از مانیتورهای مختلف به یک اندازه نیست. برای div اول ارتفاع...
۱۳۹۹/۰۵/۰۷

form الهام
در:
سلام یه سوال داشتم که هرچی سرچ کردم جوابش پیدا نشد چجوری ادامه مطلب رو با کلیک روی کلمه مثلا بیشتر... ببینیم؟ ...
۱۳۹۹/۰۵/۰۶

form فاطمه
در:
سلام و خسته نباشید من اومدم برای وبم کد نظرات جدید درج کنم و اتفاقی یه بخش بزرگی از کدها رو حذف کردم و...
۱۳۹۹/۰۵/۰۵
form دینا
در:
چطور نظرات خصوصی که واسه وبلاگم مینویسن پاسخ بدم
۱۳۹۹/۰۵/۰۳
form میثم
در:
سلام من برای دریافت چند تا اطلاعات از جداول سایتم مجبور شدم دستور زیر رو اجرا کنم. هر کدام از جداول حدود ۱.۰۰۰.۰۰۰...
۱۳۹۹/۰۵/۰۱
form علی
در:
با سلام و تشکر فراوان اگر یک div خودش درون div دیگری باشد مثل مثال زیر مقدارش رو چطور به دست بیاریم؟ در...
۱۳۹۹/۰۵/۰۱
form mahtab
در:
خیلی میبخشین بفرمایین
۱۳۹۹/۰۴/۳۱
form علی
در:
با سلام و درود فراوان با چه فرمانی میشه content یک متاتگ رو به دست آورد. مثلا یه لینکی رو بدیم و content مورد...
۱۳۹۹/۰۴/۳۰
form فاطمه
در:
سلام چرا وبلاگ ها برام بالا نمیاد فقط بخش مدیریت میاد وقتی میزنی مشاهده وبلاگ نمیاد وبلاگ دوستانم نمیاد حتی وبلاگ های دیگه...
۱۳۹۹/۰۴/۲۸
form امیر
در:
سلام می خواستم بپرسم چگونه می شه در وبلاگ خود هنگامی که بادید کننده وارد وبلاگ می شه آهنگ خودکار پخش بشه . ممنون...
۱۳۹۹/۰۴/۲۶
form mahtab
در:
سلام ببخشید من که اینو نوشتم شما هم جواب دادین : ببخشین چرا وبلاگ من تو لبتاپ دوستم باز نمیشه ؟؟؟ واسه...
۱۳۹۹/۰۴/۲۶
form مهدی
در:
سلام حالتون خوبه؟ ببخشید هی مزاحمتون میشم.. یک سوالی داشتم من عملیات ری رایت رو میخوام تو سی پنل انجام بدم صفحه لوگین رو باز...
۱۳۹۹/۰۴/۲۶
form مهدی
در:
خیلی خیلی ممنونم از وقتی که گذاشتید.. لطف کردید
۱۳۹۹/۰۴/۲۴
form mahtab
در:
ببخشین چرا وبلاگ من تو لبتاپ دوستم باز نمیشه ؟؟؟ واسه ی ویروس هم اسکن کرده اما نوشته چیزی نیس چیکار کنیم ؟؟؟؟ ...
۱۳۹۹/۰۴/۲۴
  در انتظار بررسی: ۰
 پاسخگویی به سوالات 1 تا 48 ساعت زمان می برد.