การสืบค้นตามช่วงเวลา
นี่ก็เป็นอีกหนึ่งบทความใน “ซีรีย์คิวรี่ตามคำขอ” เพราะได้รับคำถามมา ก่อนอื่นผู้อ่านพบว่ามีผู้พัฒนาจำนวนไม่น้อยเก็บข้อมูล datetime เป็น string เพราะอาจไม่ชำนาญในการจัดการข้อมูล datetime เลยสตาฟมันไว้ในรูปแบบ string แทน ซึ่งกลายเป็นภาระในการสืบค้นเพราะเมื่อต้องการนำมาใช้ประโยชน์ก็ต้องหาทางสกัดข้อมูลจาก string มาเป็น datetime ก่อนอยู่ดี
เหตุผลที่นักพัฒนาตัดรำคาญด้วยการเก็บข้อมูล datetime ในรูปแบบ string เป็นเพราะการป้อนข้อมูล datetime นั้นมักจะป้อนเป็น string แล้วระบบจะจัดเก็บเป็น datetime ให้เอง หากแต่ string ที่ป้อนเข้ามาไม่มีความเป็นกลาง (Neutral date format) แต่ไปขึ้นอยู่กับ Locale ของฝั่ง Client
Microsoft SQL Server สามารถจำลอง Locale ฝั่ง Client ได้ผ่านคำสั่ง SET LANGUAGE
|
ผลลัพธ์ที่ได้
|
จะเห็นว่าเมื่อป้อน '05/08/2019' ลงไปหากฝั่ง Client มี Locale เป็น British แล้วจะหมายถึง 2019-08-05 หรือวันที่ 5 สิงหาคม 2562 แต่หากฝั่ง Client มี Locale เป็น US แล้วจะหมายถึง 2019-05-08 หรือวันที่ 8 พฤษภาคม 2562
แม้ว่าจะป้อนข้อมูลเหมือนกันแต่มาจาก Client ต่าง Locale กันทำให้การจัดเก็บข้อมูล date ลงบนฝั่ง SQL Server ต่างวันกันดังแสดง
แต่หากผู้ใช้เปลี่ยนการป้อนข้อมูลวันที่ที่เป็นกลาง อาทิ ‘Aug 5, 2019’ , ‘August 5, 2019’ , ‘5 Aug 2019’ , ‘5 August 2019’ , ‘2019-08-05’, ‘2019.08.05’, ‘20190805’ ไม่ว่าจะมาจาก Client ต่าง Locale กันก็จะไม่มีปัญหา ดังตัวอย่าง
|
หรือ
|
ผลลัพธ์ที่ได้คือ
Changed language setting to British. |
จะเห็นว่าแม้จะมาจาก Client ต่าง Locale กันการป้อนข้อมูลวันที่ที่เป็นกลางจะทำให้ Microsoft SQL Server ยังคงจัดเก็บข้อมูลได้ตรงตามวันที่ต้องการ ผู้เขียนจะใช้การป้อนข้อมูลวันที่ที่เป็นกลางสำหรับการทดสอบทั้งหมดในบทความนี้
การเตรียมข้อมูลตัวอย่าง
ผู้เขียนเตรียมตาราง TestOrders ตามสคริปต์ต่อไปนี้ เพื่อใช้ทดสอบการคิวรี่
|
Note:
|
หากต้องการสืบค้นใบสั่งซื้อในวันที่ 1 มกราคม 2519 โดยป้อนเพียงวันที่จะไม่ได้ผลลัพธ์แม้แต่แถวข้อมูลเดียวดังแสดง
|
ผลลัพธ์ที่ได้
OrderID OrderDate |
เหตุผลเพราะหากป้อนเพียง ‘Jan 1, 2019’ จะหมายถึง ‘Jan 1, 2019 00:00:00.000’ ซึ่งไม่ตรงกับแถวข้อมูลใดเลย การสืบค้นที่ควรคือระบุเป็นช่วงข้อมูลดังนี้
|
ผลลัพธ์ที่ได้
OrderID OrderDate |
บางท่านท้วงติงว่าทำไมไม่ใช้ BETWEEN แทน ตัวดำเนินการ BETWEEN ไม่สามารถใช้ได้เพราะจะหมายถึง
‘Jan 1 , 2019 00:00:00.000’ <= OrderDate <=’Jan 2, 2019 00:00:00.000’
ซึ่งจะมีแถวข้อมูลของวันที่ 2 มกราคม 2019 เวลาเที่ยงคืนปนมาด้วย ดังแสดง
|
ผลลัพธ์ที่ได้
OrderID OrderDate |
การคิวรี่ที่ไม่แนะนำ
ในกรณีสืบค้นชนิดข้อมูล datetime ที่ผู้เขียนมักพบบ่อย 2 แบบที่ไม่แนะนำมีดังนี้
คิวรี่ที่ไม่แนะนำแบบที่ 1
|
เป็นการแปลงค่าของคอลัมน์ OrderDate ซึ่งเป็นชนิด datetime ไปเป็น date แล้วค่อยเทียบกับ ‘Jan 1, 2019’
คิวรี่ที่ไม่แนะนำแบบที่ 2
|
เป็นการสกัดข้อมูลจากคอลัมน์ OrderDate ออกมาเป็น integer ด้วยฟังก์ชัน YEAR, MONTH และ DAY แล้วนำไปเทียบกับเลขจำนวนเต็ม
เพราะทั้งสองแนวทางเป็นการนำเอาข้อมูลจากคอลัมน์มาสร้างเป็นนิพจน์ก่อนนำไปเปรียบเทียบ ทำให้อาจไม่ได้รับประโยชน์จาก Index และมีการประมาณผลแบบ Row-by-Row นั่นเอง











