SQL Tips 06 – Lọc dữ liệu theo date và time đúng cách
Date và Time là những dữ liệu quan trọng và thường xuyên được sử dụng khi truy vấn dữ liệu. Tuy nhiên có 1 số vấn đề sau đây nếu bạn không lưu ý thì có thể sẽ viết query không chính xác.
1. Nên dùng hàm biến đổi mà có nêu rõ định dạng ngày tháng mong muốn, thay vì lệ thuộc vào thiết lặp mặc định của hệ thống
Giả sử ta có bảng dữ liệu lưu trữ tất cả các giao dịch của công ty, với thời gian giao dịch (TransactionDateTime) chi tiết đến từng giây. Ta muốn lấy dữ liệu của tất cả các giao dịch diễn ra vào ngày mùng 8 tháng 1 năm 2023 với query như sau:
SELECT
*
FROM TRANSACTION_LOG
WHERE TransactionDateTime = CAST('8/1/2023' AS DATETIME)
Query này có 2 vấn đề:
– tùy thuộc vào cơ chế thời gian của hệ thống được thiết lập mà ‘8/1/2023’ sẽ được hệ thống hiểu là mùng 8 tháng 1 hoặc mùng 1 tháng 8, nên nếu ta không nắm rõ được cơ chế của hệ thống thì kết quả trả ra sẽ dễ bị sai
– ‘8/1/2023’ khi được chuyển sang dạng DATETIME sẽ có dạng như sau 2023-01-08 00:00:00, như vậy chỉ những giao dịch diễn ra vào đúng thời điểm (giờ, phút, giấy) đó của ngày 8/1 mới được query trả ra. Vậy query đã trả ra thiếu dữ liệu so với mong muốn.
Để xử lý vấn đề này, ta viết query như sau:
SELECT
*
FROM TRANSACTION_LOG
WHERE TransactionDateTime >= CONVERT(DATETIME, '2023-01-08', 120)
and TransactionDateTime < CONVERT(DATETIME, '2023-01-09', 120)
Cách sử dụng CONVERT(DATETIME, ‘2023-01-08’, 120) đảm bảo hệ thống sẽ luôn hiểu đúng ngày tháng (ở đây là yyyy-MM-dd 00:00:00) và đảm bảo lấy được tất cả các giao dịch trong ngày 8/1.
2. Tránh dùng hàm lên cột có kiểu dữ liệu date hoặc datetime vì sẽ khiến câu lệnh không dùng được index trên các cột đó.
Ví dụ query dưới đây sẽ trả ra kết quả ta mong muốn nhưng sẽ không tận dụng được index trên cột TransactionDateTime:
SELECT
*
FROM TRANSACTION_LOG
WHERE CONVERT(DATE, TransactionDateTime) = '2023-01-08'