[MSSQL] SQL กับการบวก/ลบวันที่

วันนี้ผมได้งานจากที่่ทำงานมาให้เขียน Query เพื่อแจ้งเตือนสินค้าที่หมดอายุล่วงหน้าตามวันที่กำหนดไว้ ระหว่างวันที่กำหนดจนถึงจำนวนวันที่แจ้งเตือนล่วงหน้า โดยเอาผลัลพธ์ที่ได้มาจัดโปรโมชั่นลดแลกแจกแถมกัน (สมมติว่าเป็น 7 วัน) โดยผมค่อยๆแนะนำไปทีละขั้นตอน ดังนี้

เตรียมข้อมูล

  • กำหนดโครงสร้างตาราง ดังรูป
    โครงสร้างตารางที่ใช้ในบทความนี้
  • ใส่ช้อมูลเตรียมลงไป ดังรูป
    ข้อมูลที่ใช้ในบทความนี้

ลองผิดลองถูก
จากโจทย์มาลองแปลงเป็นแนวคิด "เลือกสินค้าที่มีวันหมดอายุอยู่ในช่วง วันที่ปัจจุบัน จนถึง วันที่ปัจจุบัน + 7 " ถ้าเอามาแปลงเป็น Query ต้องแปลงอย่างไร ใช้อะไรบ้าง ซึ่งใช้ได้หลากหลายแบบ ตอนนี้ผมขอใช้ Between ก่อน ปัญหาถัดมา คือ  วันที่ปัจจุบัน + 7 สามารถเขียน Query ได้อย่างไร เขียนแทนค่าตรงๆ หรือใช้ฟังก์ชั่นช่วย

  • ปัญหา คือ "2013-11-07"+7  ใช้ได้ หรือไม่ ?
    • ลองเขียน Query ดังนี้

      [sql]DECLARE @ProcessDate As Date = '2013-11-01'
      SELECT Product_ID, Product_Name, Unit, PricePerUnit, ExpireDate
      FROM PRODUCT
      WHERE ExpireDate BETWEEN @ProcessDate AND @ProcessDate + 7[/sql]

    • ลองรันดูพบว่าใช้ไม่ได้ เกิด Error Message ซึ่งสาเหตุของ Error เกิดจากตัวแปร Process Date มีชนิดข้อมูล Date ซึ่งไม่สามารถนำมาบวกกับ 7 ซึ่งมีชนิดข้อมูล Integer ได้
      • เพิ่มเติม: หากกำหนดชนิดข้อมูลแบบ Datetime ตัว SQL Server ยอมให้ ลบกับข้อมูลประเภท Integer ได้

      Message แจ้งเตือน

  • ลองใหม่ฟังก์ชั่น DATEADD ซึ่งมีหน้าที่จัดการบวก/ลบวันที่
    • รูปแบบการใช้งาน ดังนี้
      DATEADD (datepart , number , date )
      • datepart คือ รูปแบบของเวลา เช่น ชั่วโมง(DAY), สัปดาห์(WEEK) หรือ ไตรมาส(QUARTER) เป็นต้น
      • number คือ จำนวนเวลาที่ต้องการเพิ่ม หรือ ลบ ออก จากโจทย์ เราต้องแจ้งเตือนล่วงหน้า 7 วัน ดังนั้น number เท่ากับ 7
      • date คือ วันตั้งต้น จากโจทย์ คือ ProcessDate น้ันเอง
    • ลองเขียน Query โดยใช้ DateADD ดังนี้

      [sql]DECLARE @ProcessDate As Date = '2013-11-01'
      SELECT Product_ID, Product_Name, Unit, PricePerUnit, ExpireDate
      FROM PRODUCT
      WHERE ExpireDate BETWEEN @ProcessDate AND DATEADD(DAY, 7, @ProcessDate)[/sql]

    • เมื่อลองรัน Query พบว่าแสดงข้อมูลได้ผลลัพธ์ตรงตามต้องการ ดังรูป
      ผลลัพธ์ที่ได้

ตัวอย่างอื่นๆที่ใช้ DATEADD โดยกำหนดค่า ProcessDate ดังนี้

[sql]DECLARE @ProcessDate As Datetime = '2013-04-23 13:05:07.256'[/sql]

รูปแบบเวลารูปแบบเวลา(ตัวย่อ)Queryผลลัพธ์
MILLISECONDmsSELECT DATEADD(MILLISECOND,1500,@ProcessDate)2013-04-23 13:05:08.757
MINUTEmi, nSELECT DATEADD(MINUTE,15,@ProcessDate)2013-04-23 13:20:07.257
HOURhhSELECT DATEADD(HOUR,-3,@ProcessDate)2013-04-23 10:05:07.257
WEEKDAYdw, wSELECT DATEADD(WEEKDAY,-2,@ProcessDate)2013-04-21 13:05:07.257
WEEKwk, wwSELECT DATEADD(WEEK,4,@ProcessDate)2013-05-21 13:05:07.257
DAYdd, dSELECT DATEADD(DD,4,@ProcessDate)2013-04-27 13:05:07.257
MONTHmm, mSELECT DATEADD(MM,-4,@ProcessDate)2012-12-23 13:05:07.257
QUARTERqq, qSELECT DATEADD(Q,-2,@ProcessDate)2012-10-23 13:05:07.257
YEARyy, yyyySELECT DATEADD(YYYY,-5,@ProcessDate)2008-04-23 13:05:07.257

สรุปผล

  • จากโจทย์นี้สามารถเขียน Query ได้หลายแบบมากๆ โดยตัวอย่างที่ผมเขียนเป็นการสอนการใช้ฟังก์ชั่น DATEADD ซึ่งสรรพคุณของฟังก์ชั่นนี้สามารถลดจำนวน Code ที่ผู้อ่านเขียนได้แน่นอน และช่วยให้การทำงานของโปรแกรมของเรามีประสิทธิภาพมากยิ่งขึ้นด้วย

แหล่งอ้างอิง


Discover more from naiwaen@DebuggingSoft

Subscribe to get the latest posts to your email.