CodeGym /Các khóa học /SQL SELF /Định dạng ngày và giờ: NOW(), CURREN...

Định dạng ngày và giờ: NOW(), CURRENT_DATE, DATE_PART()

SQL SELF
Mức độ , Bài học
Có sẵn

Ngày tháng và thời gian không chỉ là những con số trừu tượng đâu, mà là chìa khóa để khai thác thông tin cực kỳ giá trị từ dữ liệu. Ngoài đời, mày gặp ngày tháng suốt: ví dụ như phân tích doanh số theo tháng, lọc theo ngày sinh nhân viên hoặc so sánh các khoảng thời gian. Biết cách xử lý ngày tháng giúp mày viết query linh hoạt hơn và rút ra được nhiều insight xịn xò.

Ví dụ, những trường hợp mà xử lý ngày tháng là cực kỳ quan trọng:

  • Phân tích doanh số trong một tháng cụ thể.
  • Đếm số lượng user đăng ký trong năm vừa qua.
  • Lập báo cáo theo khoảng thời gian (ví dụ: doanh thu hàng tháng).

Trong PostgreSQL có cả đống hàm để làm việc với ngày tháng, nhưng giờ mình chỉ giới thiệu mấy cái hữu dụng nhất thôi nha.

Những hàm cơ bản để làm việc với ngày tháng và thời gian

Hàm NOW() trả về ngày giờ hiện tại của server database. Dùng khi mày cần biết chính xác thời điểm hiện tại. Ví dụ: muốn lưu lại thời gian tạo bản ghi mới.

Cú pháp:
SELECT NOW();

Ví dụ kết quả:

2023-11-05 15:23:45.123456+00

Ví dụ sử dụng: Mày muốn chèn một đơn hàng với ngày giờ hiện tại:

INSERT INTO orders (order_id, order_date, total_amount)
VALUES (1, NOW(), 150.00);
Bình luận: ở đây NOW() sẽ tự động thêm ngày giờ hiện tại vào cột order_date.

Cách hoạt động của lệnh INSERT thì mấy bài sau sẽ nói kỹ hơn nha :P

Hàm CURRENT_DATE

Nếu chỉ cần lấy ngày hiện tại mà không quan tâm đến giờ phút giây, dùng CURRENT_DATE. Nó chỉ trả về năm, tháng, ngày thôi.

Cú pháp:

SELECT CURRENT_DATE;

Ví dụ kết quả:

2023-11-05

Ví dụ sử dụng: Giả sử mày muốn lấy các bản ghi trong ngày hôm nay:

SELECT *
FROM orders
WHERE order_date = CURRENT_DATE;
Bình luận: ở đây mình so sánh ngày trong cột order_date với ngày hiện tại.

Thêm tí vui vẻ nhé. NOW() giống như ly cà phê ở chỗ làm: sẵn sàng cho mày ngay bây giờ. Còn CURRENT_DATE thì như cái lịch treo tường: chỉ có ngày thôi, không lằng nhằng chi tiết.

Lấy các phần của ngày bằng DATE_PART()

Hàm DATE_PART() giúp mày lấy ra một phần cụ thể của ngày, ví dụ năm, tháng, ngày, giờ hoặc phút. Rất tiện để đếm số đơn hàng trong một năm nào đó hoặc xác định thứ trong tuần.

Cú pháp:

DATE_PART('phần', ngày)

Ví dụ:

SELECT DATE_PART('year', NOW()) AS current_year;

Ví dụ kết quả:

current_year
2025

Các phần của ngày mà mày có thể lấy ra:

  • year: năm.
  • month: tháng.
  • day: ngày.
  • hour: giờ.
  • minute: phút.
  • second: giây.
  • dow: thứ trong tuần (0 = chủ nhật).

Ví dụ 2: Lấy tháng từ ngày hiện tại.

SELECT DATE_PART('month', CURRENT_DATE) AS current_month;

Kết quả:

current_month
6

Có thể dùng DATE_PART() cho các phép tính phức tạp hơn. Ví dụ:

Mày muốn chọn những user sinh trong năm nay:

SELECT *
FROM students
WHERE DATE_PART('year', birth_date) = DATE_PART('year', CURRENT_DATE);

Ví dụ kết quả:

id first_name last_name birth_date grade
1 Otto Art 2025-03-12 9
2 Anna Pal 2025-07-08 8
3 Piu Wolf 2025-01-22 10
4 Eva Go 2025-09-30 7
5 Dan Sok 2025-06-14 9

Ví dụ thực tế

Một số ví dụ dưới đây có những lệnh mà mày chưa học đâu. Đừng lo, sắp tới mày sẽ làm mấy cái này như ăn kẹo thôi. Chỉ là muốn cho mày thấy nhiều ví dụ thực tế hơn. Và cũng để tăng phần hấp dẫn nữa :)

Ví dụ 1: Tính tuổi user

Giả sử có bảng users với ngày sinh của từng user. Mình muốn tính tuổi của họ.

Query:

SELECT user_id, first_name, last_name, 
       DATE_PART('year', CURRENT_DATE) - DATE_PART('year', birth_date) AS age
FROM users;

Mình chỉ cần lấy năm hiện tại trừ năm sinh. Cách này nhanh nhưng không hoàn toàn chính xác đâu nha.

Ví dụ kết quả:

user_id first_name last_name age
101 Alex Lin 25
102 Maria Chi 30
103 Tor Coz 22
104 Nat Ive 27
105 Don Sok 35

Ví dụ 2: Lọc theo thời gian

Nếu mày muốn lấy tất cả đơn hàng được tạo trong 1 tiếng vừa qua:

SELECT *
FROM orders
WHERE order_date >= NOW() - INTERVAL '1 hour';

Chú ý là dùng INTERVAL (khoảng thời gian) rất tiện nha.

Ví dụ 3: Nhóm theo tháng

Mày muốn đếm số đơn hàng mỗi tháng trong năm nay:

SELECT DATE_PART('month', order_date) AS order_month, COUNT(*) AS order_count
FROM orders
WHERE DATE_PART('year', order_date) = DATE_PART('year', CURRENT_DATE)
GROUP BY DATE_PART('month', order_date)
ORDER BY order_month;

Nhóm theo số tháng, kết quả cũng được sắp xếp theo tháng luôn.

Ví dụ kết quả:

order_month order_count
1 120
2 95
3 134
4 110
5 42

Ví dụ 4: Lấy thứ trong tuần

Mày muốn biết ngày nào trong tuần có nhiều đơn hàng nhất:

SELECT DATE_PART('dow', order_date) AS day_of_week, COUNT(*) AS order_count
FROM orders
GROUP BY DATE_PART('dow', order_date)
ORDER BY order_count DESC;

Lệnh DATE_PART('dow') sẽ trả về thứ trong tuần của mỗi đơn hàng dưới dạng số, 0 là chủ nhật, 1 là thứ hai, v.v. DOW là viết tắt của DayOfWeek - thứ trong tuần.

Ví dụ kết quả:

day_of_week order_count
5 210
4 190
3 175
2 160
1 140
6 120
0 95

Lưu ý các lỗi phổ biến

Làm việc với ngày tháng nhiều khi đau đầu vì lỗi. Đây là vài vấn đề thường gặp mà mày có thể dính phải:

Định dạng ngày giờ: khi dùng NOW() hoặc bất kỳ hàm nào trả về ngày giờ, nhớ kiểm tra định dạng của nó. Ví dụ, nếu so sánh order_date với CURRENT_DATE, đảm bảo là phần giờ bị bỏ qua hoặc được chỉ rõ ràng.

Ngày ở dạng chuỗi: nhiều khi trong database, ngày lại lưu dưới dạng text. Nếu mày dùng các hàm xử lý ngày tháng (như DATE_PART()), sẽ bị lỗi ngay. Đảm bảo dữ liệu có kiểu DATE hoặc TIMESTAMP nha.

Múi giờ khác nhau: nếu server chạy ở một múi giờ, còn dữ liệu lấy từ múi giờ khác, dễ bị rối lắm. Hãy cân nhắc dùng kiểu TIMESTAMPTZ để xử lý múi giờ.

Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION