GORAGOD.com

การแสดงรายการที่เกี่ยวข้อง (Related)

การแสดงรายการที่เกี่ยวข้องกัน ปกติจะใช้กับพวก บทความ หรือข่าว เช่น การแบ่งบทความออกเป็นตอนๆ แล้วเชื่อมทุกตอนเข้าด้วยกันด้วย relate หรือ การแสดงข่าวของ ชมพู่ และ รายการช่าวอื่นๆของ ชมพู่ เป็นต้น
SELECT id,topic,relate FROM table_name WHERE relate='ทำเว็บให้มีคนดู'

คำสั่ง SQL ด้านบนคือการค้นหารายการที่เกี่ยวข้องกัน (relate เหมือนกัน) ได้ผลลัพท์ดังตาราง
id topic relate
218 ทำเว็บให้มีคนดู (ตอนที่ 1) ทำเว็บให้มีคนดู
219 ทำเว็บให้มีคนดู (ตอนที่ 2) ทำเว็บให้มีคนดู
398 ทำเว็บให้มีคนดู (ตอนที่ 4) ทำเว็บให้มีคนดู
449 ทำเว็บให้มีคนดู (ตอนที่ 5) ทำเว็บให้มีคนดู
450 ทำเว็บให้มีคนดู (ตอนที่ 6) ทำเว็บให้มีคนดู
451 ทำเว็บให้มีคนดู (ตอนที่ 7) ทำเว็บให้มีคนดู
452 ทำเว็บให้มีคนดู (ตอนที่ 8) ทำเว็บให้มีคนดู
453 ทำเว็บให้มีคนดู (ตอนที่ 9) ทำเว็บให้มีคนดู
454 ทำเว็บให้มีคนดู (ตอนที่ 10) ทำเว็บให้มีคนดู
220 ทำเว็บให้มีคนดู (ตอนที่ 3) ทำเว็บให้มีคนดู
3733 ทำเว็บให้มีคนดู (ตอนที่ 11) ทำเว็บให้มีคนดู
จากข้อมูลตัวอย่างด้านบน จะเห็นได้ว่า id ของรายการ ไม่ได้อยู่ใกล้เคียงกันเพียงพอที่จะทำให้ "การ Query ข้อมูลใกล้เคียงตามจำนวนที่กำหนด" สามารถแสดงผลได้อย่างถูกต้อง (ในตัวอย่างนี้หากใช้วิธีที่ผมกล่าวถึง รายการที่ 3733 จะไม่ถูกนำมาแสดงผลเลย เนื่องจากผลลัพท์จากคำสั่ง ABS() จะอยู่ห่างจากรายการที่ต้องการมากจนอาจมีรายการอื่นมาแสดงผลแทน)

การแก้ไขเราอาจต้องใช้เทคนิคอื่นในการจัดการเพิ่มเติม (ตัวอย่างนี้จะหารายการที่เกี่ยวข้องกับ id=449 จำนวน x รายการ)
SELECT @row:=@row+1 AS row,
y.* FROM (SELECT id,topic,relate FROM table_name WHERE id>449 ORDER BY id ASC LIMIT x) AS y
,(SELECT @row:=0) AS r

ขั้นแรกเราจะ query เอารายการที่มากกว่า 449 ออกมา พร้อมใส่เลขลำดับ โดยเรียงตามลำดับ id ซึ่งจะได้ผลลัพท์ดังตาราง
row id topic relate
1 450 ทำเว็บให้มีคนดู (ตอนที่ 6) ทำเว็บให้มีคนดู
2 451 ทำเว็บให้มีคนดู (ตอนที่ 7) ทำเว็บให้มีคนดู
3 452 ทำเว็บให้มีคนดู (ตอนที่ 8) ทำเว็บให้มีคนดู
4 453 ทำเว็บให้มีคนดู (ตอนที่ 9) ทำเว็บให้มีคนดู
6 454 ทำเว็บให้มีคนดู (ตอนที่ 10) ทำเว็บให้มีคนดู
6 3733 ทำเว็บให้มีคนดู (ตอนที่ 11) ทำเว็บให้มีคนดู
หมายเหตุ ใน DB เวอร์ชั่นใหม่ๆ จะไม่สามารถเรียงลำดับใน Sub Query ได้ เพื่อให้การเรียงลำดับมีผล จึงจำเป็นต้องใส่ LIMIT เพื่อบังคับให้ DB เรียงลำดับ Query ย่อยด้วย โดยที่ตัวแปร x ให้แทนที่ด้วยจำนวนผลลัพท์ที่ต้องการ

ขั้นต่อไปเราจะ Query เอารายการก่อนรายการที่ 449
SELECT @row:=@row+1 AS row,
y.* FROM (SELECT id,topic,relate FROM table_name WHERE id<449 ORDER BY id DESC LIMIT x) AS y
,(SELECT @row:=0) AS r

ซึ่งจะได้ผลลัพท์เป็น
row id topic relate
1 398 ทำเว็บให้มีคนดู (ตอนที่ 4) ทำเว็บให้มีคนดู
2 220 ทำเว็บให้มีคนดู (ตอนที่ 3) ทำเว็บให้มีคนดู
3 219 ทำเว็บให้มีคนดู (ตอนที่ 2) ทำเว็บให้มีคนดู
4 218 ทำเว็บให้มีคนดู (ตอนที่ 1) ทำเว็บให้มีคนดู
นำผลลัพท์ทั้งสองส่วนมารวมกันด้วย UNION โดยเรียงลำดับตาม row และจำกัดจำนวนตามที่ต้องการ
SELECT * FROM (
(SELECT @row:=@row+1 AS row,
y.* FROM (SELECT id,topic,relate FROM table_name WHERE id>449 ORDER BY id ASC LIMIT x) AS y
,(SELECT @row:=0) AS r)
UNION
(SELECT @row2:=@row2+1 AS row2,
y.* FROM (SELECT id,topic,relate FROM table_name WHERE id<449 ORDER BY id DESC LIMIT x) AS y
,(SELECT @row2:=0) AS r)
) AS Z ORDER BY row LIMIT x

จะได้ผลลัพท์เป็น (ผลลัพท์ตามตัวอย่างนี้ กำหนดให้ x=4)
row id topic relate
1 398 ทำเว็บให้มีคนดู (ตอนที่ 4) ทำเว็บให้มีคนดู
1 450 ทำเว็บให้มีคนดู (ตอนที่ 6) ทำเว็บให้มีคนดู
2 220 ทำเว็บให้มีคนดู (ตอนที่ 3) ทำเว็บให้มีคนดู
2 451 ทำเว็บให้มีคนดู (ตอนที่ 7) ทำเว็บให้มีคนดู
ถ้าสังเกตุ ตอนนี้เราได้ผลลัพท์ที่ต้องการแล้ว แต่หากเอาไปแสดงผลเลย มันคงเรียงลำดับไม่ค่อยน่าดูเท่าไร ก็เลยต้องมาเรียงลำดับด้วย id อีกครั้ง (รายการใหม่ขึ้นก่อน)
SELECT * FROM (
SELECT * FROM (
(SELECT @row:=@row+1 AS row,
y.* FROM (SELECT id,topic,relate FROM table_name WHERE id>449 ORDER BY id ASC LIMIT 4) AS y
,(SELECT @row:=0) AS r)
UNION
(SELECT @row2:=@row2+1 AS row2,
y.* FROM (SELECT id,topic,relate FROM table_name WHERE id<449 ORDER BY id DESC LIMIT 4) AS y
,(SELECT @row2:=0) AS r)
) AS Z ORDER BY row LIMIT 4
) AS Z2 ORDER BY id DESC

และ นี่คือผลลัพท์ที่เราต้องการ
row id topic relate
2 451 ทำเว็บให้มีคนดู (ตอนที่ 7) ทำเว็บให้มีคนดู
1 450 ทำเว็บให้มีคนดู (ตอนที่ 6) ทำเว็บให้มีคนดู
1 398 ทำเว็บให้มีคนดู (ตอนที่ 4) ทำเว็บให้มีคนดู
2 220 ทำเว็บให้มีคนดู (ตอนที่ 3) ทำเว็บให้มีคนดู