 |
|
ขอถามในห้องภาษา PHP นะครับ เพราะใช้ PHP ในการเชื่อมต่อ Database แต่เรื่องที่จะถามส่วนใหญ่เกี่ยวกับ SQL ครับ
คือผมทำ webboard
แล้วต้องการ query แล้ว loop โชว์
ชื่อกระทู้ , วัน-เวลาที่ตั้งกระทู้ , จำนวนคนดูกระทู้ , ชื่อผู้ตั้งกระทู้ , ชื่อผู้ที่คอมเม้นล่าสุด , วันเวลาที่คอมเม้นล่าสุด
การออกแบบ Database ของผมเป็นแบบนี้ครับ
มี
- tb_member
member_id
member_name
- tb_board_topic
topic_id
topic_title
topic_detail
topic_date
topic_view
topic_by :::: link กับ member_id
- tb_board_comment
comment_id
comment_detail
comment_date
comment_by :::: link กับ member_id
comment_topic :::: link กับ topic_id
โดยปกติแล้ว ถ้าวิธีที่ง่ายสุดในการ SELECT เลยคือ
ทำการ SELECT หา topic ก่อน แล้ว Loop ตาม Topic ที่ได้ จากนั้นใน Loop ถึง SELECT หา last comment ของ Topic นั้นอีกที
ประมาณนี้
Code (PHP)
$sql = "SELECT topic_title,topic_date,topic_view,member_name as topic_by FROM tb_board_topic INNER JOIN tb_member ON topic_by=member_id ORDER BY topic_date DESC";
$query_topic = mysql_query($sql);
while($result_topic=mysql_fetch_array($query_topic)){
$sql = "SELECT comment_date , member_name as comment_by FROM tb_board_comment INNER JOIN tb_member ON comment_by=member_id WHERE comment_topic='".$result_topic['topic_id']."' ORDER BY topic_date DESC";
$query_comment = mysql_query($sql);
$result_comment = mysql_fetch_array($query_comment);
#field ที่ได้คือ
#topic_title , topic_date , topic_by (เป็นชื่อ member_name) , comment_date , comment_by (เป็นชื่อ member_name)
}
ซึ่งจากตัวอย่างข้างบน จำนวนครั้งที่ query จะเท่ากับ
1 + N
ซึ่ง N จะเป็นจำนวนของ topic ที่ได้ แล้วมา Loop แล้วใน Loop นั้นต้อง query เพื่อหา Last Comment อีกที
สมมุติได้จำนวน Topic ทั้งหมด 100 Topic ก็จะต้องมีการ Query ทั้งหมด 1 + 100 = 101 ครั้ง
แต่ที่อยากได้คือ ทำการ SELECT ครั้งเดียว แล้วได้ข้อมูลตามข้างบนทั้งหมด แล้ว ค่อย Loop แสดงผล
ซึ่งถ้าทำวิธีนี้ได้ ก็จะ ใช้การ Query แค่ 1 ครั้ง
ถ้าใช้ JOIN ระหว่าง topic กับ comment แบบนี้
Code
SELECT topic_title ,topic_date ,topic_view ,member_name AS topic_by_name ,comment_date FROM tb_board_topic
INNER JOIN tb_member ON member_id=topic_by
LEFT OUTER JOIN tb_board_comment ON comment_topic=topic_id
ORDER BY board_comment_date DESC, board_topic_date DESC
แบบนี้จะเกิดปัญหาดังนี้ครับ
- เราจะได้ member_name ของ tb_board_comment ได้อย่างไร เพราะไม่สามารถ INNER JOIN tb_member ON member_id=comment_by อีกได้
- ข้อมูลที่ SELECT มานั้น ในกรณีมีจำนวน N topic มีจำนวน M comment จะได้จำนวนแถว ที่ query เท่ากับ N topic คูณ M comment
ซึ่งจริงๆต้องการแค่ N topic กับ 1 comment ล่าสุด
อาจแก้ปัญหาโดยใช้ GROUP BY เข้ามาช่วยเป็นแบบนี้
Code
SELECT topic_title ,topic_date ,topic_view ,member_name AS topic_by_name ,comment_date FROM tb_board_topic
INNER JOIN tb_member ON member_id=topic_by
LEFT OUTER JOIN tb_board_comment ON comment_topic=topic_id
GROUP BY topic_id
ORDER BY board_comment_date DESC, board_topic_date DESC
ผลลัพธ์ ที่ได้จะเป็น N topic กับ 1 comment
แต่ comment ที่ได้จะไม่เรียงตาม comment_date DESC
ตอนนี้เท่าที่คิดได้คือ ใช้ SELECT ซ้อน SELECT จะเป็นแบบนี้ครับ
Code
SELECT
topic_title,
topic_date,
topic_view,
member_name AS topic_by_name,
(SELECT member_name FROM tb_comment INNER JOIN tb_member ON member_id=comment_by WHERE comment_topic=topic_id ORDER BY comment_date DESC LIMIT 0,1) AS comment_by_name ,
(SELECT comment_date FROM tb_comment INNER JOIN tb_member ON member_id=comment_by WHERE comment_topic=topic_id ORDER BY comment_date DESC LIMIT 0,1) AS comment_date
FROM tb_topic
INNER JOIN tb_member ON topic_by=member_id
ORDER BY topic_date DESC
เท่าที่สังเกตคือ การ SELECT ซ้อน ตรง Field นั้น จะเลือกได้แค่ 1 Field ไม่สามารถเลือกมา 2 Field ในการ SELECT ได้
Code
SELECT member_name,comment_date FROM tb_comment INNER JOIN tb_member ON member_id=comment_by WHERE comment_topic=topic_id ORDER BY comment_date DESC LIMIT 0,1
จะมีวิธีการ SELECT แบบอื่นอีกหรือไม่ครับ
หรือว่าการ SELECT -> Loop - > SELECT ตามแบบวิธีแรกสุดนั้นดีสุดแล้วครับ
เพราะที่คิดไว้คือ ถ้ายิ่ง query น้อยครั้ง ก็ยิ่งดีใช่หรือไม่
อยากให้ช่วยแชร์ความรู้กันทีครับ 
พวกเว็บบอร์ดใหญ่ๆ เค้าทำกันอย่างไร
พวกบอร์ด สำเร็จรูป ผมก็ไม่เคยไปหาแกะโค้ด มาดู 
Tag : PHP, MySQL
|
|
 |
 |
 |
 |
Date :
2012-01-26 11:22:40 |
By :
Likito |
View :
2894 |
Reply :
5 |
|
 |
 |
 |
 |
|
|
|
 |