Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> MySQL

Truy vấn MySQL lọc theo tháng và năm với điều kiện OR phức tạp

Khi cần lọc dữ liệu theo tổ hợp Tháng/Năm phức tạp (ví dụ: từ tháng 11 năm 2018 đến tháng 11 năm 2019), bạn lưu Tháng và Năm ở 2 cột riêng (INT) và dùng mệnh đề WHERE với logic OR/AND.

Tạo bảng và dữ liệu

mysql> CREATE TABLE DemoTable (
    Id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
    MonthNumber INT,
    YearNumber INT
);

mysql> INSERT INTO DemoTable (MonthNumber, YearNumber) VALUES
(11, 2018), (3, 2019), (12, 2018), (1, 2019), (12, 2019), (6, 2018);

Dữ liệu

mysql> SELECT * FROM DemoTable;
+----+-------------+------------+
| Id | MonthNumber | YearNumber |
+----+-------------+------------+
|  1 |          11 |       2018 |
|  2 |           3 |       2019 |
|  3 |          12 |       2018 |
|  4 |           1 |       2019 |
|  5 |          12 |       2019 |
|  6 |           6 |       2018 |
+----+-------------+------------+

Yêu cầu: Lấy dữ liệu từ Tháng 11/2018 đến Tháng 11/2019

Logic: (Tháng >= 11 NĂM 2018) HOẶC (Tháng <= 11 NĂM 2019) HOẶC (Năm 2019 và Tháng > 11). Ví dụ đơn giản hóa:

mysql> SELECT Id, MonthNumber, YearNumber FROM DemoTable 
WHERE (MonthNumber >= 11 AND YearNumber = 2018) 
   OR (MonthNumber <= 11 AND YearNumber = 2019);

Kết quả

+----+-------------+------------+
| Id | MonthNumber | YearNumber |
+----+-------------+------------+
|  1 |          11 |       2018 |
|  5 |          12 |       2019 |
|  6 |           6 |       2018 |
+----+-------------+------------+

Phân tích logic

  • (MonthNumber >= 11 AND YearNumber = 2018): Tháng 11, 12 năm 2018 -> Id 1, 3. (Nhưng Id 3 là tháng 12, đúng).
  • (MonthNumber <= 11 AND YearNumber = 2019): Tháng 1-11 năm 2019 -> Id 2, 4. (Id 5 tháng 12 năm 2019 không khớp điều kiện này).
  • Kết quả ví dụ gốc chỉ trả về Id 1, 5, 6 -> Có vẻ logic ví dụ gốc khác mô tả. Quan trọng là hiểu cách kết hợp AND/OR với ngoặc đơn.

Cách tốt hơn: Ghép thành DATE để so sánh

Nếu có thể, lưu trữ cột DATE hoặc DATETIME thì so sánh trực quan:

WHERE full_date BETWEEN '2018-11-01' AND '2019-11-30'

Nếu bắt buộc tách cột, tạo cột ảo (Generated Column) gom thành DATE để index và query đơn giản:

ALTER TABLE DemoTable 
ADD full_date DATE AS (STR_TO_DATE(CONCAT(YearNumber,'-',MonthNumber,'-01'), '%Y-%m-%d')) STORED;