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

مطالبی که تا این لحظه از بخش آموزش مقدماتی 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
دسته بندی: آموزش مقدماتی » MySQL
برچسب ها: MySQL
« بعدی

استفاده از WHERE در پرس و جوی MySQL
اتصال PHP به MySQL با اکستنشن MySQLi
انتخاب ردیف ها با دستور SELECT در MySQL
نحوه ذخیره کردن اطلاعات با دستور INSERT در MySQL
توابع تجمیعی (Aggregate Functions) در MySQL
دیدگاه


مجتبی
۱۷:۲۴ ۱۳۹۳/۱۲/۲۴
سلام وقت بخیر
من می خوام دو تا جدول انتخاب واحد و دانشجو رو که دارم پیوند بدم این کار رو هم انجام دادم ، الان نیاز دارم که یک شرط استفاده کنم که سطرهایی رو نشون بده که کد استادیش برابر فلان باشد
می تونید کمک کنید که شرط رو باید چجوری و کجا بنویسم اینم دستوراتم هست
من می خوام دو تا جدول انتخاب واحد و دانشجو رو که دارم پیوند بدم این کار رو هم انجام دادم ، الان نیاز دارم که یک شرط استفاده کنم که سطرهایی رو نشون بده که کد استادیش برابر فلان باشد
می تونید کمک کنید که شرط رو باید چجوری و کجا بنویسم اینم دستوراتم هست
FROM selectv WHERE pid='$prof_id'
INNER JOIN course
ON course.crsid=selectv.crsid
INNER JOIN stud
ON stud.stid=selectv.stid
INNER JOIN proof
ON selectv.pid=proof.pid
سلام
بررسی ساختار دقیق دیتابیس و هدف شما برای ارائه پاسخ دقیق ضروری است، با این حال به نظر می توانید از AND برای WHERE اول استفاده کنید.
بررسی ساختار دقیق دیتابیس و هدف شما برای ارائه پاسخ دقیق ضروری است، با این حال به نظر می توانید از AND برای WHERE اول استفاده کنید.
محمد
۱۸:۴۲ ۱۳۹۳/۱۲/۱۵
بازم سلام..... اون دو تا راه اول رو میدونستم ولی منظور من برای هک کردن همون راه سوم بود که متوجه شدم :) تشکرررررررر..
به نظر شما چرا information_schema هست؟ خیلی خطر ناکه
به نظر شما چرا information_schema هست؟ خیلی خطر ناکه
سلام
information_schema مرکز خلاصه اطلاعات کل جداول و ستون های MySQL است و این خود گویا است که دستکاری پرس و جوهای تنظیم شده برای کار با آن (به فرض حمله از نوع Injection) می تواند به کل ساختار آسیب برساند.
information_schema مرکز خلاصه اطلاعات کل جداول و ستون های MySQL است و این خود گویا است که دستکاری پرس و جوهای تنظیم شده برای کار با آن (به فرض حمله از نوع Injection) می تواند به کل ساختار آسیب برساند.
محمد
۱۷:۳۹ ۱۳۹۳/۱۲/۱۲
سلام. من با چه کدی میتونم مثلا کالومن هشتم یه دیتابیس رو سلکت کنم؟
سلام
این شیوه توصیه نمی شود چون در شرایط مختلف (به فرض تغییرات بعدی)، کدهای شما دچار مشکل خواهند شد! اما جهت اطلاع چند راه حل وجود دارد، راه حل ابتدایی این است که با
این شیوه توصیه نمی شود چون در شرایط مختلف (به فرض تغییرات بعدی)، کدهای شما دچار مشکل خواهند شد! اما جهت اطلاع چند راه حل وجود دارد، راه حل ابتدایی این است که با
SELECT * FROM
تمام ستون های یک جدول را انتخاب و با$row = mysql_fetch_row()
در اصطلاح ستون ها را fetch کرده و در حلقه while مقادیر کلید مورد نظر را بر اساس شماره استخراج کنید، به فرض:$row[7]
، روش دیگر که حرفه ای است، استفاده از INFORMATION_SCHEMA و ORDINAL_POSITION است، مثال:SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'your database schema' AND TABLE_NAME = 'your table name' AND ORDINAL_POSITION = 8;
نکته: database schema همان نام دیتابیس است و table name نام جدول، به این ترتیب از دیتابیس خلاصه اطلاعات MySQL یا همان INFORMATION_SCHEMA، جدول COLUMNS بر اساس ستون TABLE_SCHEMA و TABLE_NAME و همچنین ORDINAL_POSITION می توان مقدار COLUMN_NAME را به دست آورد.reza
۲۱:۵۹ ۱۳۹۳/۱۰/۱۲
سلام ببخشید بازم مزاحمتون شدم
عزیز من مشکلم بر طرف نشد
این موارد رو گذاشتم
از این دو تا خطی که توی صفحه گذاشتم ارور میگیره
البته بعد از وارد کردن آدرس صفحه get.php به شکل زیر در میاد
لطفاً بنده رو راهنمایی بفرمایید
عزیز من مشکلم بر طرف نشد
<form action="get.php">
از تاریخ<input name="from date" value="تاریخ را وارد کنید">
<br>
تا تاریخ<input name="to date" value="تاریخ را وارد کنید">
<button type="submit">ارسال</button>
</form>
این رو توی یک صفحه قرار دادم ، توی یک صفحه دیگه با اسم get.phpاین موارد رو گذاشتم
<table border="1" bordercolor="#000000" style="width:95%;">
<?php
$date_1 = mysql_real_escape_string($_POST['from date'], $con);
$date_2 = mysql_real_escape_string($_POST['to date'], $con);
include_once("config.php");
$con = mysql_connect($db_host,$db_user,$db_pass) or die("خطا در اتصال به پايگاه داده");
$selected=mysql_select_db($db_name, $con) or die("خطا در انتخاب پايگاه داده");
$dbresult=mysql_query("SELECT * FROM $db_table WHERE date > $date_1 AND date < $date_2 ORDER BY id DESC");
while($amch=mysql_fetch_assoc($dbresult))
{
echo
" <td> "
.$amch["id"].
" </td><td> "
.$amch["ip"].
" </a></td><td> "
.$amch["country"].
" </td><td> "
.$amch["date"].
" </td><td> "
.$amch["time"].
" </td><td> "
.$amch["device"].
" </td><td> "
.$amch["browser"].
"</td></tr>"
;}
?>
</table>
اما وقتی تاریخ رو وارد میکنم و دکمه ارسال رو میزنم ارور میدهاز این دو تا خطی که توی صفحه گذاشتم ارور میگیره
$date_1 = mysql_real_escape_string($_POST['from date'], $con);
$date_2 = mysql_real_escape_string($_POST['to date'], $con);
این دو تا رو چیکار کنم که ارور نده و تاریخ رو اعمال کنه ؟البته بعد از وارد کردن آدرس صفحه get.php به شکل زیر در میاد
get.php?from+date=2015-01-02&to+date=2014-12-28
که تا اینجاش فکر میکنم درست کار شده ، اما در ادامه ارور میده و خروجی دیتابیس رو نمایش نمیده و از دو تا بخش $date_1 و $date_2 ارور میگیرهلطفاً بنده رو راهنمایی بفرمایید
سلام
تابع mysql_real_escape_string را زمانی استفاده کنید که تابع mysql_connect (اتصال دیتابیس) اجرا شده باشد، به عبارتی تکه کد اول را بعد از تکه کد مربوط به اتصال قرار دهید تا ابتدا لینک متغیر con ایجاد و سپس از آن استفاده شود! نوع دیتای مربوط به تاریخ در دیتابیس نیز باید به صورت DATETIME باشد نه چیز دیگری.
تابع mysql_real_escape_string را زمانی استفاده کنید که تابع mysql_connect (اتصال دیتابیس) اجرا شده باشد، به عبارتی تکه کد اول را بعد از تکه کد مربوط به اتصال قرار دهید تا ابتدا لینک متغیر con ایجاد و سپس از آن استفاده شود! نوع دیتای مربوط به تاریخ در دیتابیس نیز باید به صورت DATETIME باشد نه چیز دیگری.
الیاس
۱۸:۱۷ ۱۳۹۳/۰۴/۲۰
نه منظور من این نبود فایل را برایتان ایمیل کردم
ممنون
ممنون
با بررسی فایل این پرس و جو راه حل مشکل شما است:
SELECT matlab.title, subject.name
FROM `matlab` , `subject` , `rel`
WHERE matlab.id = rel.ida
AND rel.idb = subject.id
LIMIT 0 , 30
الیاس
۱۳:۲۹ ۱۳۹۳/۰۴/۱۹
سلام
یه سوال:
فرض کنید چند تا جدول دارید
جدول مطالب: کد مطلب - عنوان مطلب - کد نویسنده - کد زبان - و...
رکورد-> 100 تست 2 1
جدول نویسندگان: کد نویسنده - نام نویسنده
رکورد-> 1 امید
رکورد-> 2 علی
جدول زبان: کد زبان - نام زبان
رکورد-> 1 فارسی
رکورد-> 2 انگلیسی
جدول موضوعات: کد موضوع - عنوان موضوع
رکورد-> 1 ورزشی
رکورد-> 2 اجتماعی
جدول رابط مطلب و موضوع: کد موضوع - کد مطلب
رکورد-> 1 100
رکورد-> 2 100
حال sql می خوام که خروجی مثل زیر باشه
کد مطلب: 100
عنوان مطلب: تست
نام نویسنده: علی
زبان: فارسی
موضوع: ورزشی - اجتماعی
یه سوال:
فرض کنید چند تا جدول دارید
جدول مطالب: کد مطلب - عنوان مطلب - کد نویسنده - کد زبان - و...
رکورد-> 100 تست 2 1
جدول نویسندگان: کد نویسنده - نام نویسنده
رکورد-> 1 امید
رکورد-> 2 علی
جدول زبان: کد زبان - نام زبان
رکورد-> 1 فارسی
رکورد-> 2 انگلیسی
جدول موضوعات: کد موضوع - عنوان موضوع
رکورد-> 1 ورزشی
رکورد-> 2 اجتماعی
جدول رابط مطلب و موضوع: کد موضوع - کد مطلب
رکورد-> 1 100
رکورد-> 2 100
حال sql می خوام که خروجی مثل زیر باشه
کد مطلب: 100
عنوان مطلب: تست
نام نویسنده: علی
زبان: فارسی
موضوع: ورزشی - اجتماعی
سلام
اگر درست متوجه ساختار دیتابیس شده باشیم با پرس و جویی ترکیبی مشابه دستورات زیر مشکلتان حل می شود (البته بدون تست نمی توان پاسخ دقیق داد، برای دریافت پاسخ دقیق نمونه فایل sql دیتابیس را به آدرس ایمیل ما (موجود در بخش تماس) ارسال کنید تا بررسی کنیم):
اگر درست متوجه ساختار دیتابیس شده باشیم با پرس و جویی ترکیبی مشابه دستورات زیر مشکلتان حل می شود (البته بدون تست نمی توان پاسخ دقیق داد، برای دریافت پاسخ دقیق نمونه فایل sql دیتابیس را به آدرس ایمیل ما (موجود در بخش تماس) ارسال کنید تا بررسی کنیم):
SELECT tbl_1.col_1, tbl_1.col_2, tbl_1.col_3, tbl_2.col_1, tbl_3.col_1 FROM tbl_1 INNER JOIN tbl_2 ON tbl_1.col_1 = tbl_2.col_1 INNER JOIN tbl_3 ON tbl_1.col_2 = tbl_3.col_1
abbas
۰۴:۲۶ ۱۳۹۳/۰۴/۰۸
سلام ببخشید چرا جملات فارسی که از دیتابیس میگیرم بصورت علامت سوال ؟؟؟ دیده میشه و جملات فارسی هم که به سرور میفرستم کلمات ناخوانا دیده میشه فیلدی هم که در دیتابیس برای این جملات در نظر گرفتم utf8_persian_ci هست
سلام
در مجموع برای اینکه مشکلی از لحاظ ذخیره و نمایش حروف فارسی در دیتابیس نداشته باشید باید تمام مراحل زیر را به صورت صحیح انجام دهید:
در درجه اول باید Server connection collation دیتابیس را
- از متاتگ زیر در تمام صفحات استفاده کنید:
- پس از اتصال با دیتابیس، پرس و جوی زیر را هم اجرا کنید:
در مجموع برای اینکه مشکلی از لحاظ ذخیره و نمایش حروف فارسی در دیتابیس نداشته باشید باید تمام مراحل زیر را به صورت صحیح انجام دهید:
در درجه اول باید Server connection collation دیتابیس را
utf8_persian_ci
انتخاب کنید، سپس مراحل زیر را انجام دهید:- از متاتگ زیر در تمام صفحات استفاده کنید:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- علاوه بر دیتابیس، جداول و ستون ها را نیز با یونیکدutf8_persian_ci
بسازید.- پس از اتصال با دیتابیس، پرس و جوی زیر را هم اجرا کنید:
mysql_query ("SET NAMES 'utf8' ");
- اگر مشکل همچنان حل نشد، فایل های خود را با ویرایشگر ++Notepad باز کرده و سپس از قسمت Encoding گزینه Encoding UTF-8 without BOM را انتخاب و فایل خود را مجددا ذخیره نمائید.۱۶:۵۷ ۱۳۹۳/۰۳/۲۵
با سلام وخسته نباشید
من دو تا جدول دارم با نام های test , test2 و فیلد های
id ( در هر دو جدول)
title ( در هر دو جدول)
newssport (برای جدول test)
news (برای جدول test2)
حالا میخواستم فیلد title هر دو جدول رو در یک جا نمایش بدم و به صورت نزولی باشند
اگه راهنماییم کنید ممنون میشم .
من دو تا جدول دارم با نام های test , test2 و فیلد های
id ( در هر دو جدول)
title ( در هر دو جدول)
newssport (برای جدول test)
news (برای جدول test2)
حالا میخواستم فیلد title هر دو جدول رو در یک جا نمایش بدم و به صورت نزولی باشند
اگه راهنماییم کنید ممنون میشم .
سلام
با استفاده از UNION یا UNION ALL این کار ممکن است، مثال:
با استفاده از UNION یا UNION ALL این کار ممکن است، مثال:
SELECT id, title FROM test UNION ALL SELECT id, title FROM test2 ORDER BY id ASC
yaser
۱۶:۳۲ ۱۳۹۳/۰۲/۳۰
ببخشید چطور میشه برای یک فیلد عددی محدودیت ایجاد کرد یعنی میخوام اعداد فقط 0 تا 10 درونش قابل نوشتن باشه
بهتر است این کار در کدنویسی PHP و به طور مثال با دستورات شرطی انجام شود، مثال:
<?php
$number = 12;
if($number >= 0 && $number <= 10){
//insert
}
?>
در MySQL باید از TRIGGER استفاده کنید که ساده نیست.Hosein
۱۵:۰۴ ۱۳۹۳/۰۱/۲۷
سلام
دو تا جدول کارم جدول خبر و گروه
جدول خبر: کد خبر (کلید اصلی)، زمان، عنوان، کد گروه (کلید خارجی)
جدول گروه: کد گروه (کلید اصلی)، عنوان ، زمان
میخوام کوئری بنویسم که توی هر روز چند عدد خبر با چه عنوان هایی و هر خبر مربوط به کدوم گروه خبری است
چطوری باید نوشت؟
دو تا جدول کارم جدول خبر و گروه
جدول خبر: کد خبر (کلید اصلی)، زمان، عنوان، کد گروه (کلید خارجی)
جدول گروه: کد گروه (کلید اصلی)، عنوان ، زمان
میخوام کوئری بنویسم که توی هر روز چند عدد خبر با چه عنوان هایی و هر خبر مربوط به کدوم گروه خبری است
چطوری باید نوشت؟
سلام
برای بدست آوردن تعداد، هم می توانید با COUNT پرس و جوی مجزا بنویسید، هم از توابعی مانند mysql_num_rows (در صورتی که از اکستنشن mysql استفاده می کنید) استفاده کنید و هم در حلقه یک مقدار عددی را به میزان دور آن افزایش دهید تا تعداد خبرها مشخص شود، اما برای مورد دوم لطفا آموزش مربوط به نحوه استفاده از JOIN (به طور خاص قسمت LEFT JOIN) را مطالعه کنید، با مثال توضیح داده شده.
برای بدست آوردن تعداد، هم می توانید با COUNT پرس و جوی مجزا بنویسید، هم از توابعی مانند mysql_num_rows (در صورتی که از اکستنشن mysql استفاده می کنید) استفاده کنید و هم در حلقه یک مقدار عددی را به میزان دور آن افزایش دهید تا تعداد خبرها مشخص شود، اما برای مورد دوم لطفا آموزش مربوط به نحوه استفاده از JOIN (به طور خاص قسمت LEFT JOIN) را مطالعه کنید، با مثال توضیح داده شده.
مهران
۰۲:۰۱ ۱۳۹۲/۱۲/۰۵
سلام
شرمنده من در مورد داده های سلسله مراتبی سوال داشتم. البته شاید با همین join هم اجرا بشه. به هر حال بنده جدولی دارم که نظرات رو دریافت میکنه نظرات بینندگان رو. این جدول من id داره، newsid داره که نظر مربوط به هر خبر رو ثبت میکنه. parent_id هم داره. و سایر اطلاعات کار parent_id من اینه که نظر معمولی رو که بیننده ارسال میکنه 0 ارسال میکنه تو قسمت post.حالا من برای هر نظر پاسخ گذاشتم که بیننده به هر نظر یک پاسخ ارسال کنه. حالا من یبارم به parent_id آیدی نظر اصلی رو ارسال میکنه و تو parent_id ثبت میکنه. یعنی parent_id نظر اصلی 0 و parent_id پاسخ ها آیدی نظر اصلی. تا اینجا مشکلی ندارم. حالا میخوام بدونم کوئری رو چطوری بنویسم که سلسله مراتبی رعایت بشه و نظرات اصلی به همراه زیر مجموعه هاش به نمایش دربیاد.
من از طریق حلقه زیر نظرات رو نمایش میدم
شرمنده من در مورد داده های سلسله مراتبی سوال داشتم. البته شاید با همین join هم اجرا بشه. به هر حال بنده جدولی دارم که نظرات رو دریافت میکنه نظرات بینندگان رو. این جدول من id داره، newsid داره که نظر مربوط به هر خبر رو ثبت میکنه. parent_id هم داره. و سایر اطلاعات کار parent_id من اینه که نظر معمولی رو که بیننده ارسال میکنه 0 ارسال میکنه تو قسمت post.حالا من برای هر نظر پاسخ گذاشتم که بیننده به هر نظر یک پاسخ ارسال کنه. حالا من یبارم به parent_id آیدی نظر اصلی رو ارسال میکنه و تو parent_id ثبت میکنه. یعنی parent_id نظر اصلی 0 و parent_id پاسخ ها آیدی نظر اصلی. تا اینجا مشکلی ندارم. حالا میخوام بدونم کوئری رو چطوری بنویسم که سلسله مراتبی رعایت بشه و نظرات اصلی به همراه زیر مجموعه هاش به نمایش دربیاد.
من از طریق حلقه زیر نظرات رو نمایش میدم
$comments = getcomments ($newsid);
<?php
if ($comments ) { ?>
<?php while ($commentsrow = mysql_fetch_assoc($comments)){?>
<div class="comentpost">
<div class="comentpostname"><?php echo' ' .$commentsrow ['name'] ?> </div>
<div class="comentposttext"> <?php echo' ' .$commentsrow ['body'] ?></div>
<?php }?>
<?php }?>
و توی فایل جداگانه ای کوئری رو نوشتم که بصورت زیر هست
function getComments ($newsid)
{
$result = mysql_query("SELECT * FROM comments WHERE newsid = '$newsid' AND active=1 ORDER BY id DESC
");
$rows = mysql_num_rows($result);
if ($rows>0) return $result;return false;
}
البته اینها فقط نظر اصلی رو دریافت میکنه. ممنون میشم یه راهنمایی کوچیکی کنید که کوئری رو چطوری بنویسم؟ و اینکه میخوام بدونم باید دو تا کوئری بنویسم که کوئری دوم پاسخ ها رو نمایش بده و تو حلقه ی جداگانه نمایش بدم یا نه؟ با join باید ارتباط بدم. اگر امکانش هست یه کوئری نمونه رو بنویسید تا من بر اساس اون انجام بدمسلام
دوست گرامی ساختار دیتابیس شما باید دقیق بررسی شود، صرف توضیحات خیلی به درک ساختار کمکی نمی کند (در این حالت زمانبر است!)، به هر صورت به نظر با دستور join می توانید موارد اشتراکی بین دو جدول را مطابق نیازتان استخراج کنید، به نمونه های موجود در آموزش و همچنین پاسخ نظراتی که پیش تر ارسال شده توجه کنید، احتمالا پاسختان را خواهید گرفت (باید کمی تمرکز کنید!).
دوست گرامی ساختار دیتابیس شما باید دقیق بررسی شود، صرف توضیحات خیلی به درک ساختار کمکی نمی کند (در این حالت زمانبر است!)، به هر صورت به نظر با دستور join می توانید موارد اشتراکی بین دو جدول را مطابق نیازتان استخراج کنید، به نمونه های موجود در آموزش و همچنین پاسخ نظراتی که پیش تر ارسال شده توجه کنید، احتمالا پاسختان را خواهید گرفت (باید کمی تمرکز کنید!).
مسعود
۲۳:۵۲ ۱۳۹۲/۱۱/۲۴
بله کاملا متوجه شدم. ارایه و حلقه ها رو هم میدونم. ولی خب مساله اصلی من این بود که میخواستم ببینم با این روش انجام میشه یا خیر؟
من با کوئری زیر کامنت ها رو دریافت میکنم
من با کوئری زیر کامنت ها رو دریافت میکنم
function getComments ($newsid)
{
$result = mysql_query("SELECT * FROM comments WHERE newsid = '$newsid' AND active=1 ORDER BY id DESC
");
یعنی جدول اصلی من comments هست که کوئری رو بصورت بالا دریافت کردم و نظرات رو نشون میدم. حالا جدول دیگه ای دارم به نام replaycomments که توش ستون id و commentsid رو دارم commentsid ای دی اصلی جدول comments رو دریافت میکنه و نشون میده که این پاسخ برای اون نظر هست. حالا میخوام اون جدول رو با این اتصال بدم که کامنت اصلی رو نشون بده و جواب های نظر رو زیر اون نشون بده. ممنون میشم یه راهنمایی بفرمایید. یه پیشنهادی هم دارم یه انجمن هم راه بندازید بهتر میشه. یا یه چیزی مثل question answerبرای این کار می توانید از LEFT JOIN استفاده کنید، مثال:
SELECT comments.name, comments.text, replaycomments.replay
FROM comments
LEFT JOIN replaycomments ON comments.id = replaycomments.commentsid
LIMIT 0 , 30
نکته: این فقط یک پرس و جوی فرضی و جهت راهنمایی است، ممکن است با توجه به ساختار جدول نیاز به تغییراتی باشد، خروجی پرس و جو از طریق توابعی مانند mysql_fetch_array قابل تجزیه است، همچنین برای درک بهتر ابتدا به صورت تستی در برنامه phpMyAdmin پرس و جو را امتحان کنید.مسعود
۲۲:۱۵ ۱۳۹۲/۱۱/۲۳
با سلام و احترام
من برای قسمت نظرات ارسال پاسخ به هر نظر رو گذاشتم و قسمت ارسال نظر جدول comments و برای پاسخ ها جدول replaycomments اولا میخواستم بدونم این روش درسته یا نه؟ بعد حالا من قسمت ارسال نظر رو مشکل ندارم بیننده میاد نظر میده و نظرش تو comments همچنین با گرفتن newsid آیدی خبر ذخیره میشه الان مشکلم تو ارسال پاسخ هست که ایا باید join کنم که نظر اصلی ثبت بشه و نظراتی که زیر مجموعه اون هستند زیر اون ثبت بشه یا نه فرق داره؟
من تو جدول replaycomments آیدی خبر newsid و همچنین آیدی نظر اصلی رو commentsid رو سایر اطلاعات رو دریافت می کنم! من بصورت عادی توی حلقه اول نظر اصلی بعد حلقه بعدی پاسخ ها رو دریافت می کنم اما پاسخ ها فقط به نظری که اول ارسال شده زیر اون قرار می گیره؟
من برای قسمت نظرات ارسال پاسخ به هر نظر رو گذاشتم و قسمت ارسال نظر جدول comments و برای پاسخ ها جدول replaycomments اولا میخواستم بدونم این روش درسته یا نه؟ بعد حالا من قسمت ارسال نظر رو مشکل ندارم بیننده میاد نظر میده و نظرش تو comments همچنین با گرفتن newsid آیدی خبر ذخیره میشه الان مشکلم تو ارسال پاسخ هست که ایا باید join کنم که نظر اصلی ثبت بشه و نظراتی که زیر مجموعه اون هستند زیر اون ثبت بشه یا نه فرق داره؟
من تو جدول replaycomments آیدی خبر newsid و همچنین آیدی نظر اصلی رو commentsid رو سایر اطلاعات رو دریافت می کنم! من بصورت عادی توی حلقه اول نظر اصلی بعد حلقه بعدی پاسخ ها رو دریافت می کنم اما پاسخ ها فقط به نظری که اول ارسال شده زیر اون قرار می گیره؟
سلام
دوست گرامی بدون بررسی دقیق کدها و ساختار دیتابیس شما نمی توان درک درستی از هدف و مشکلتان داشت، اما در کل طراحی ساختار دیتابیس در اکثر موارد یک کار سلیقه ای است و روش خاصی برای آن وجود ندارد (یعنی هم می توان در یک جدول تمام موارد را خلاصه کرد هم اینکه برای هر بخش اصلی، یک جدول جداگانه در نظر گرفت)، البته افراد با تجربه تر معمولا تمام موارد را مد نظر می گیرند، اگر واقعا ایجاد دو جدول ضرورت داشت، هیچ ایرادی بر این کار متصور نیست (منتها باید نحوه استفاده از پرس و جوهای ترکیبی و کار با آرایه ها، حلقه ها و... را به خوبی بلد باشید).
دوست گرامی بدون بررسی دقیق کدها و ساختار دیتابیس شما نمی توان درک درستی از هدف و مشکلتان داشت، اما در کل طراحی ساختار دیتابیس در اکثر موارد یک کار سلیقه ای است و روش خاصی برای آن وجود ندارد (یعنی هم می توان در یک جدول تمام موارد را خلاصه کرد هم اینکه برای هر بخش اصلی، یک جدول جداگانه در نظر گرفت)، البته افراد با تجربه تر معمولا تمام موارد را مد نظر می گیرند، اگر واقعا ایجاد دو جدول ضرورت داشت، هیچ ایرادی بر این کار متصور نیست (منتها باید نحوه استفاده از پرس و جوهای ترکیبی و کار با آرایه ها، حلقه ها و... را به خوبی بلد باشید).
رضا
۱۶:۱۰ ۱۳۹۲/۱۱/۱۷
ممنون مطلب رو گرفتم فقط برای سایت هایی که کاربران قابلیت ثبت نام دارن و میتونن به هم پیام بدن باید جدول رو به چه شکل طراحی کرد
طراحی جدول بستگی به نیاز شما دارد، در اینگونه سایت ها هم می توان با یک جدول کارهای مورد نظر را انجام داد، در هر صورت منطقی نیست که ساخت جدول در دیتابیس مبتنی بر تعداد کاربران باشد! به فرض می توان یک ستون برای دریافت کننده پیام در نظر گرفت (که می تواند تا حد ممکن ردیف اطلاعاتی داشته باشد)، هر پیامی که ارسال می شود یک دریافت کننده مشخص (در ستون مربوطه) دارد و لذا اطلاعات درهم نمی شود!
به نظر تمام مشکلات شما از عدم آشنایی کافی با نحوه طراحی و استفاده از جداول و ستون ها در دیتابیس است.
به نظر تمام مشکلات شما از عدم آشنایی کافی با نحوه طراحی و استفاده از جداول و ستون ها در دیتابیس است.
رضا
۲۱:۵۹ ۱۳۹۲/۱۱/۱۵
ببخشید من با مفاهیم پایگاه داده اشنایی نسبی دارم
آیا منظور شما اینه که یک فیلد text برای هر کاربر وجود داره که تمام پیام های اون رو شامل میشه؟ یا اینکه برای هر پیام باید یک فیلد text جداگانه داشته باشیم؟ اگه مورد دوم منظور شماست در نتیجه ما باید چه تعداد فیلد text برای یک کاربر در نظر بگیریم در حالی که نمی دونیم چه تعداد پیام ارسالی داره
آیا منظور شما اینه که یک فیلد text برای هر کاربر وجود داره که تمام پیام های اون رو شامل میشه؟ یا اینکه برای هر پیام باید یک فیلد text جداگانه داشته باشیم؟ اگه مورد دوم منظور شماست در نتیجه ما باید چه تعداد فیلد text برای یک کاربر در نظر بگیریم در حالی که نمی دونیم چه تعداد پیام ارسالی داره
نوع برداشت شما از دیتابیس صحیح نیست! در جداول شما ستون ها را مشخص می کنید و سطر های اطلاعات معمولا به صورت خودکار (تا جایی که ظریفیت جدول یا ستون id اجازه دهد) ذخیره می شوند، مثال:
id name comment
1 Ali متن پیام
2 Kourosh متن پیام
3 Mehrdad متن پیام
- به سوالات کلی، زمانبر، مبهم و مشکلاتی که تلاشی برای رفع آنها نکرده باشید پاسخ مختصر داده شده یا به بخش برنامه نویسی اختصاصی ارجاع داده می شوند.
- کدها و اسکریپت های طولانی را ترجیحا در یک صفحه وب آنلاین یا به صورت حساب موقت و آزمایشی قرار دهید تا امکان بررسی دقیق مشکل و خطایابی میسر باشد.
- تمام دیدگاه های ارسالی خوانده شده و برای هر کاربر مدت زمان لازم جهت پاسخگویی در نظر گرفته می شود، لطفا از طرح سوالات متعدد در بازه زمانی کوتاه خودداری کنید.