การ Query บางทีก็ต้องการข้อมูลเป็น ช่วงของเวลา
เช่น
2014-6-16 02:00:00 A
2014-6-16 04:00:00 B
2014-6-16 06:00:00 C
2014-6-16 08:00:00 D
คงต้องมีให้ใช้กันบ้างใช่ไหมครับ
นั่งคิดอยู่นานว่าจะทำยังไง
จนคิดวิธีนี้ออก วิธียัดสมการคำนวนวันที่ไปตรงๆนี่แหละครับ ฮ่าๆๆ
ไม่ค่อยได้ใช้ความสามารถของ sqlserver ซักเท่าไหร่
ลองดูกันนะครับ ...
ก่อนอื่นก็เตรียมตัวแปรที่จำเป็นให้เรียบร้อย
DECLARE @start_date DATETIME = '2014-07-06 21:00:00' ;
DECLARE @end_date DATETIME = '2014-07-08 5:00:00' ;
DECLARE @i INT = 7;
@i ก็คือตัวแปร ที่ใช้บอกว่า "เอาข้อมูลทุกๆ กี่ชั่วโมง" นะครับ
พอตระเตรียมตัวแปรกันเสร็จก็บรรเลงเลย
;WITH dta AS
(
SELECT
MIN(booking_date ) AS 'Date',
COUNT(booking_id ) AS 'Total_Bookings'
FROM myTable (nolock)
WHERE booking_date between @start_date and @end_date
GROUP BY (DATEDIFF( DAY,@start_date ,booking_date)* 24+DATEPART (HOUR, booking_date)-DATEPART (HOUR, @start_date))/@i
)
SELECT * FROM dta ORDER BY dta.[Date] ;
อธิบายโค้ดหน่อย
การใช้ ;WITH (name) AS (...)
เป็นการสร้าง TEMP VARIABLE แบบใช้ได้แค่ อีกครั้งเดียว พอใช้เสร็จ ตัวแปรนี้ก็จะหายไป
เช่น
ผมสร้าง
;WITH dta AS
(
SELECT * FROM myTable;
)
เนี่ย พอสร้างเสร็จ
ผมสามารถเขียนโค้ดต่อว่า
SELECT * FROM dta; ถึงตรงนี้ยังใช้ได้ครับ (พอเสร็จจากบรรทัดนี้ dta ก็จะหายไป)
ถ้ามีการเรียกใช้ dta อีก มันก็จะหาไม่เจอแล้ว (บางคนคิดว่าไม่มีประโยชน์ จริงๆแล้วมันมีนะครับ มันสามารถทำให้การเขียนโค้ดเป็น Cascading Style ได้)
อ้ออ ลืมบอกไป
ผมมี Naming Convention ตรงการตั้งชื่อตัวแปร table ที่สร้างขึ้น
ผมจะเขียนเป็น dta ย่อมาจาก "Derived Table A"
ถ้ามีการสร้าง table ขึ้นมาอีก ผมก็จะรันมันไปเรื่อย
dta, dtb, dtc ...
ง่ายดีมั้ยครับ ฮ่าๆๆ
ต่อไปก็ตรงใจความสำคัญเลย (ซึ่งผมก็ไม่รู้จะเขียนอธิบายยังไงเหมือนกัน)
เอาเป็นว่า ใช้หลักการ ตั้ง start_date ให้เป็น 0 แล้วมันก็จะสามารถหาร HOUR_INTERVAL ได้โดยง่าย ...(เอาเป็นว่า ลองทำความเข้าใจดูเอาเองละกันนะครับ ฮ่าๆๆ)
และผลลัพธ์ก็จะได้ดังนี้
ใครมีวิธีที่ดีกว่านี้ แบ่งปันกันนะครับ
ขอบคุณครับ
ReplyDelete