วันนี้จะมาเขียนข้อมูลเกี่ยวกับ sql ที่ได้เขียนมา โจทย์ก็ตามหัวข้อเลยครับ คือให้ดึงข้อมูลจากตาราง 7 วันล่าสุด และถ้าวันไหนไม่มีข้อมูลให้โชว์ Value เป็น 0
คือปกติเวลาคิวรี่ข้อมูล มันจะแสดงข้อมูลเฉพาะที่มีขึ้นมาแสดงใช่ไหมครับ เช่น สมมุติข้อมูลมี ดังภาพด้านล่าง
เวลาเราคิวรี่ข้อมูล 7 วันล่าสุด ก็จะใช้โค้ดประมาณนี้
SELECT * FROM challenge_table WHERE challenge_date BETWEEN DATE_SUB(NOW(), INTERVAL 7 DAY) AND NOW()
ข้อมูลที่จะได้ ก็จะแสดงดังภาพด้านล่าง
แต่ถ้าสิ่งที่เราอยากได้คือ แสดงวันที่ทั้งหมด 7 วัน ไม่ได้แสดงแค่สองวันที่โชว์ล่ะ เราจะทำอย่างไรดี (ติ๊กต๊อก ๆ ๆ ๆ )
สิ่งที่เราทำก็คือต้องสร้างวันที่ขึ้นมาก่อน จากนั้นก็ค่อยข้อมูลมา join นี่คือกระบวนการคิดที่เจมส์ใช้นะครับ ซึ่งคุณผู้อ่านมีวิธีการอื่นที่ดีกว่าก็สามารถแนะนำเข้ามาได้เน้อ ผมจะได้ทราบวิธีอื่น แต่เอาเป็นว่า ลองวิธีนี้ดูก่อนละกันนะจ๊ะ
โดยการสร้างวันที่ในส่วนแรก โค้ดก็จะประมาณนี้
select date(NOW()) as date_week union all
select date(DATE_SUB(NOW(),INTERVAL 1 DAY)) union all
select date(DATE_SUB(NOW(),INTERVAL 2 DAY)) union all
select date(DATE_SUB(NOW(),INTERVAL 3 DAY)) union all
select date(DATE_SUB(NOW(),INTERVAL 4 DAY)) union all
select date(DATE_SUB(NOW(),INTERVAL 5 DAY)) union all
select date(DATE_SUB(NOW(),INTERVAL 6 DAY))
ข้อมูลที่ได้ก็จะเป็นวันที่ที่เราต้องการ ถ้าลองเอาโค้ดนี้ไป Run ดูจะพบว่าข้อมูลที่ได้จะเป็นดังภาพด้านล่าง (อาจจะแตกต่างกันตรงที่วันที่จะเป็นที่ปัจจุบันจนถึงวันที่ของ 6 วันที่แล้ว)
คราวนี้เราก็เอาตารางมาจอยกัน คือ คิวรี่ข้อมูล 7 วันล่าสุด กับ ตารางวันที่ ที่เราสร้างขึ้นมา โค้ดที่จะได้ก็จะประมาณนี้
SELECT
*, date_week
FROM
(
select date(NOW()) as date_week union all
select date(DATE_SUB(NOW(),INTERVAL 1 DAY)) union all
select date(DATE_SUB(NOW(),INTERVAL 2 DAY)) union all
select date(DATE_SUB(NOW(),INTERVAL 3 DAY)) union all
select date(DATE_SUB(NOW(),INTERVAL 4 DAY)) union all
select date(DATE_SUB(NOW(),INTERVAL 5 DAY)) union all
select date(DATE_SUB(NOW(),INTERVAL 6 DAY))
) date_create
LEFT JOIN challenge_table
ON date(challenge_table.challenge_date) = date(date_create.date_week)
คือเราจะเอา Challenge_table มาจอย เนื่องจาก เราต้องการข้อมูลของวันที่ที่เราสร้างขึ้นมาให้แสดงครบ ข้อมูลที่ได้จะแสดงดังภาพด้านล่าง
คราวนี้เราจะมาปรับโค้ดนิดหน่อยให้แสดงข้อมูลที่ต้องการจริง ๆ เท่านั้น และข้อมูลที่เป็น Null เราจะปรับให้แสดงเป็น 0 เพื่อที่จะได้ตรงกับความต้องการของเรา โค้ดที่ปรับใหม่จะเป็นดังนี้
SELECT
date_week, IF(challenge_value, challenge_value, 0) as challenge_value
FROM
(
select date(NOW()) as date_week union all
select date(DATE_SUB(NOW(),INTERVAL 1 DAY)) union all
select date(DATE_SUB(NOW(),INTERVAL 2 DAY)) union all
select date(DATE_SUB(NOW(),INTERVAL 3 DAY)) union all
select date(DATE_SUB(NOW(),INTERVAL 4 DAY)) union all
select date(DATE_SUB(NOW(),INTERVAL 5 DAY)) union all
select date(DATE_SUB(NOW(),INTERVAL 6 DAY))
) date_create
LEFT JOIN challenge_table
ON date(challenge_table.challenge_date) = date(date_create.date_week)
ORDER BY date_week DESC
คือเราจะให้แสดงวันที่ และค่าออกมาเท่านั้น จากในโค้ดจะเห็นคำสั่ง IF(challenge_value, challenge_value, 0) ซึ่งหมายถึงว่า ถ้าข้อมูล Challenge_value มีข้อมูล หรือเป็นจริง จะแสดงข้อมูล challenge_value แต่ถ้าเป็นเท็จหรือ null จะแสดง 0 แทน และเราเพิ่มในส่วน ORDER BY date_week DESC ขึ้นมาเพื่อให้แสดงข้อมูลจากวันที่ล่าสุดไล่ไปตามลำดับ ข้อมูลที่ได้จะแสดงดังภาพด้านล่าง