ดึงข้อมูลจากตาราง 7 วันล่าสุด ถ้าข้อมูลวันที่อันไหนไม่มีข้อมูลให้โชว์ Value เป็น 0

วันนี้จะมาเขียนข้อมูลเกี่ยวกับ sql ที่ได้เขียนมา โจทย์ก็ตามหัวข้อเลยครับ คือให้ดึงข้อมูลจากตาราง 7 วันล่าสุด และถ้าวันไหนไม่มีข้อมูลให้โชว์ Value เป็น 0

คือปกติเวลาคิวรี่ข้อมูล มันจะแสดงข้อมูลเฉพาะที่มีขึ้นมาแสดงใช่ไหมครับ เช่น สมมุติข้อมูลมี ดังภาพด้านล่าง

ข้อมูลในตาราง challenge_table

เวลาเราคิวรี่ข้อมูล 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 ขึ้นมาเพื่อให้แสดงข้อมูลจากวันที่ล่าสุดไล่ไปตามลำดับ ข้อมูลที่ได้จะแสดงดังภาพด้านล่าง

ข้อมูลที่ได้จากการคิวรี่ข้อมูล