So sánh và Xử lý ngày trong MySQL: Hướng dẫn toàn diện kèm ví dụ & mẹo tối ưu hiệu năng

目次

1. Giới thiệu

Xử lý ngày trong MySQL là một trong những khía cạnh quan trọng nhất của các hoạt động cơ sở dữ liệu. Ví dụ, khi tổng hợp dữ liệu bán hàng theo ngày hoặc tìm kiếm các bản ghi trong một khoảng thời gian cụ thể, việc so sánh ngày trở nên thiết yếu.

Bài viết này giải thích toàn bộ từ những kiến thức cơ bản về thao tác và so sánh ngày trong MySQL đến các trường hợp sử dụng nâng cao và kỹ thuật tối ưu hiệu năng. Nó được thiết kế để hữu ích cho người dùng ở mọi cấp độ, từ người mới bắt đầu đến các nhà phát triển trung cấp.

2. Tổng quan về các Kiểu Dữ liệu Ngày trong MySQL

Các Kiểu Dữ liệu Ngày và Đặc điểm của chúng

MySQL cung cấp ba kiểu dữ liệu ngày chính sau. Dưới đây là mô tả ngắn gọn cho mỗi kiểu.

  1. DATE
  • Giá trị Lưu trữ: Năm-Tháng-Ngày ( YYYY-MM-DD )
  • Đặc điểm: Không bao gồm thông tin thời gian, phù hợp để quản lý các ngày đơn giản.
  • Trường hợp sử dụng: Ngày sinh, hạn chót.
  1. DATETIME
  • Giá trị Lưu trữ: Năm-Tháng-Ngày và Thời gian ( YYYY-MM-DD HH:MM:SS )
  • Đặc điểm: Bao gồm thông tin thời gian, phù hợp để ghi lại các dấu thời gian chính xác.
  • Trường hợp sử dụng: Dấu thời gian tạo, dấu thời gian cập nhật lần cuối.
  1. TIMESTAMP
  • Giá trị Lưu trữ: Năm-Tháng-Ngày và Thời gian ( YYYY-MM-DD HH:MM:SS )
  • Đặc điểm: Phụ thuộc vào múi giờ, hữu ích cho việc quản lý ngày và thời gian trên các khu vực khác nhau.
  • Trường hợp sử dụng: Dữ liệu log, bản ghi giao dịch.

Cách Chọn Kiểu Dữ liệu Phù hợp

  • Nếu không cần thời gian, chọn DATE.
  • Nếu cần thời gian, chọn DATETIME hoặc TIMESTAMP tùy thuộc vào yêu cầu múi giờ của ứng dụng.

Truy vấn Mẫu

Dưới đây là một ví dụ sử dụng mỗi kiểu dữ liệu.

CREATE TABLE events (
    event_id INT AUTO_INCREMENT PRIMARY KEY,
    event_date DATE,
    event_datetime DATETIME,
    event_timestamp TIMESTAMP
);

3. Cách So sánh Ngày

Sử dụng các Toán tử So sánh Cơ bản

Trong MySQL, các toán tử sau được sử dụng để so sánh ngày.

  1. = (Bằng)
  • Lấy các bản ghi khớp với ngày được chỉ định.
    SELECT * FROM events WHERE event_date = '2025-01-01';
    
  1. > / < (Lớn hơn / Nhỏ hơn)
  • Tìm kiếm các bản ghi trước hoặc sau ngày được chỉ định.
    SELECT * FROM events WHERE event_date > '2025-01-01';
    
  1. <= / >= (Nhỏ hơn hoặc bằng / Lớn hơn hoặc bằng)
  • Tìm kiếm trong một khoảng mà bao gồm ngày được chỉ định.
    SELECT * FROM events WHERE event_date <= '2025-01-10';
    

Truy vấn Khoảng bằng BETWEEN

Toán tử BETWEEN cho phép bạn dễ dàng chỉ định một khoảng ngày.

SELECT * FROM events 
WHERE event_date BETWEEN '2025-01-01' AND '2025-01-31';

Lưu ý Quan trọng:

  • BETWEEN bao gồm cả giá trị bắt đầu và kết thúc, vì vậy hãy chắc chắn rằng không có dữ liệu cần thiết nào bị loại trừ một cách không mong muốn khỏi khoảng của bạn.

4. Tính Khoảng cách Ngày

Sử dụng Hàm DATEDIFF

Hàm DATEDIFF() tính khoảng cách (theo ngày) giữa hai ngày.

SELECT DATEDIFF('2025-01-10', '2025-01-01') AS days_difference;

Kết quả:

  • 9 ngày

Sử dụng Hàm TIMESTAMPDIFF

Hàm TIMESTAMPDIFF() cho phép bạn tính khoảng cách theo các đơn vị cụ thể như năm, tháng, ngày hoặc giờ.

SELECT TIMESTAMPDIFF(MONTH, '2025-01-01', '2025-12-31') AS months_difference;

Kết quả:

  • 11 tháng

5. Cộng và Trừ Ngày

Thao tác Ngày bằng Câu lệnh INTERVAL

Trong MySQL, bạn có thể dễ dàng cộng hoặc trừ thời gian từ một ngày bằng cách sử dụng câu lệnh INTERVAL. Điều này cho phép bạn tạo các truy vấn để lấy các ngày trước hoặc sau một khoảng thời gian cụ thể.

Thêm vào Ngày

Ví dụ về việc cộng thời gian vào một ngày bằng INTERVAL:

SELECT DATE_ADD('2025-01-01', INTERVAL 7 DAY) AS plus_seven_days;

Kết quả:
2025-01-08

Trừ khỏi Ngày

Bạn có thể trừ thời gian khỏi một ngày theo cách tương tự bằng INTERVAL:

SELECT DATE_SUB('2025-01-01', INTERVAL 1 MONTH) AS minus_one_month;

Kết quả:
2024-12-01

Trường hợp sử dụng: Hệ thống nhắc nhở

Đây là một truy vấn mẫu để lấy các sự kiện xảy ra chính xác bảy ngày trước, có thể được sử dụng để gửi thông báo nhắc nhở tự động.

SELECT event_name, event_date 
FROM events 
WHERE event_date = DATE_SUB(CURDATE(), INTERVAL 7 DAY);

Tính toán dựa trên ngày hiện tại

  • CURDATE() : Trả về ngày hiện tại (YYYY-MM-DD).
  • NOW() : Trả về ngày và thời gian hiện tại (YYYY-MM-DD HH:MM:SS).

Ví dụ: Tính ngày một tuần từ hôm nay.

SELECT DATE_ADD(CURDATE(), INTERVAL 7 DAY) AS next_week;

6. Các ví dụ truy vấn thực tế

Lấy bản ghi cho một ngày cụ thể

Lấy các sự kiện khớp với ngày đã chỉ định.

SELECT * 
FROM events 
WHERE event_date = '2025-01-01';

Lấy dữ liệu trong một khoảng ngày

Ví dụ tìm kiếm các sự kiện trong khoảng một tuần.

SELECT * 
FROM events 
WHERE event_date BETWEEN '2025-01-01' AND '2025-01-07';

Tổng hợp dữ liệu theo ngày

Truy vấn này đếm số sự kiện được đăng ký cho mỗi tháng.

SELECT MONTH(event_date) AS event_month, COUNT(*) AS total_events 
FROM events 
GROUP BY MONTH(event_date);

Kết quả ví dụ:

event_monthtotal_events
110
215

7. Tối ưu hoá hiệu suất

Tìm kiếm hiệu quả bằng chỉ mục

Đặt chỉ mục trên cột ngày có thể cải thiện đáng kể hiệu suất truy vấn.

Tạo chỉ mục

SQL sau tạo một chỉ mục trên cột event_date.

CREATE INDEX idx_event_date ON events(event_date);

Kiểm tra hiệu quả của chỉ mục

Bạn có thể sử dụng EXPLAIN để kiểm tra kế hoạch thực thi truy vấn.

EXPLAIN SELECT * 
FROM events 
WHERE event_date = '2025-01-01';

Lưu ý quan trọng khi sử dụng hàm

Sử dụng hàm trong mệnh đề WHERE có thể làm mất khả năng sử dụng chỉ mục.

Ví dụ kém

Trong truy vấn sau, hàm DATE() ngăn chỉ mục được sử dụng.

SELECT * 
FROM events 
WHERE DATE(event_date) = '2025-01-01';

Ví dụ cải tiến

Khuyến nghị so sánh giá trị trực tiếp mà không dùng hàm.

SELECT * 
FROM events 
WHERE event_date >= '2025-01-01' 
  AND event_date < '2025-01-02';

8. Câu hỏi thường gặp (FAQ)

Câu hỏi 1: Sự khác nhau giữa DATE và DATETIME là gì?

  • A1:
  • DATE: Lưu chỉ ngày ( YYYY-MM-DD ). Dùng khi không cần thông tin thời gian.
  • DATETIME: Lưu cả ngày và thời gian ( YYYY-MM-DD HH:MM:SS ). Dùng khi cần dấu thời gian chính xác của một sự kiện.

Ví dụ:

CREATE TABLE examples (
    example_date DATE,
    example_datetime DATETIME
);

Câu hỏi 2: Khi chỉ định khoảng ngày bằng BETWEEN, tôi cần lưu ý gì?

  • A2:
  • BETWEEN bao gồm cả ngày bắt đầu và ngày kết thúc, nếu ngày kết thúc không có giá trị thời gian, bạn có thể không lấy được tất cả các bản ghi mong muốn.

Ví dụ:

-- This query may not retrieve records such as "2025-01-31 23:59:59"
SELECT * 
FROM events 
WHERE event_date BETWEEN '2025-01-01' AND '2025-01-31';

Cải thiện:
Đặt rõ thời gian kết thúc là 23:59:59 hoặc sử dụng so sánh bỏ qua phần thời gian.

SELECT * 
FROM events 
WHERE event_date >= '2025-01-01' AND event_date < '2025-02-01';

Câu hỏi 3: Làm thế nào để xử lý sự khác biệt múi giờ?

  • A3: Trong MySQL, kiểu TIMESTAMP phụ thuộc vào múi giờ. Ngược lại, kiểu DATETIME lưu giá trị cố định và không bị ảnh hưởng bởi múi giờ.

Kiểm tra cài đặt múi giờ hiện tại:

SHOW VARIABLES LIKE 'time_zone';

Thay đổi cài đặt múi giờ:

SET time_zone = '+09:00'; -- Japan Standard Time (JST)

Câu hỏi 4: Làm sao để lấy dữ liệu trong 30 ngày qua?

  • A4: Bạn có thể kết hợp CURDATE() hoặc NOW() với INTERVAL để lấy dữ liệu trong 30 ngày qua.

Ví dụ:

SELECT * 
FROM events 
WHERE event_date >= DATE_SUB(CURDATE(), INTERVAL 30 DAY);

Q5: Làm thế nào để cải thiện hiệu suất so sánh ngày?

  • A5:
  • Tạo chỉ mục: Đặt chỉ mục trên các cột ngày.
  • Tránh sử dụng hàm: Sử dụng hàm trong mệnh đề WHERE có thể vô hiệu hoá chỉ mục, vì vậy hãy dùng so sánh trực tiếp thay thế.

9. Tóm tắt

Các điểm chính của bài viết này

Bài viết này cung cấp một giải thích toàn diện về các kỹ thuật thao tác và so sánh ngày trong MySQL. Các điểm quan trọng như sau:

  1. Hiểu các đặc điểm và cách sử dụng đúng các kiểu dữ liệu ngày (DATE, DATETIME, TIMESTAMP).
  2. Các phương pháp so sánh cơ bản ( = , > , < , BETWEEN , v.v.).
  3. Tính toán sự chênh lệch ngày ( DATEDIFF() , TIMESTAMPDIFF() ).
  4. Cải thiện hiệu suất thông qua việc tạo chỉ mục và thiết kế truy vấn tối ưu.

Chúng tôi hy vọng hướng dẫn này giúp bạn xử lý các thao tác ngày trong MySQL một cách hiệu quả và phát triển các truy vấn thực tiễn, tối ưu cho các ứng dụng thực tế.