Không có thủ tục được lưu trữ, bảng tạm thời, chỉ một truy vấn và một kế hoạch thực thi hiệu quả được cung cấp một chỉ mục trên cột ngày:
select
subdate(
'2012-12-31',
floor(dateDiff('2012-12-31', dateStampColumn) / 30) * 30 + 30 - 1
) as "period starting",
subdate(
'2012-12-31',
floor(dateDiff('2012-12-31', dateStampColumn) / 30) * 30
) as "period ending",
count(*)
from
YOURTABLE
group by floor(dateDiff('2012-12-31', dateStampColumn) / 30);
Rõ ràng là điều gì đang xảy ra ở đây, ngoại trừ câu thần chú này:
floor(dateDiff('2012-12-31', dateStampColumn) / 30)
Biểu thức đó xuất hiện nhiều lần và nó đánh giá số khoảng thời gian 30 ngày trước dateStampColumn
Là. dateDiff
trả về số ngày chênh lệch, chia cho 30 để lấy trong khoảng thời gian 30 ngày và nạp tất cả vào floor()
để làm tròn nó thành một số nguyên. Sau khi có số này, chúng ta có thể GROUP BY
nó và hơn nữa, chúng tôi thực hiện một chút phép toán để chuyển ngược con số này thành ngày bắt đầu và ngày kết thúc của khoảng thời gian.
Thay thế '2012-12-31'
với now()
nếu bạn thích. Dưới đây là một số dữ liệu mẫu:
CREATE TABLE YOURTABLE
(`Id` int, `dateStampColumn` datetime);
INSERT INTO YOURTABLE
(`Id`, `dateStampColumn`)
VALUES
(1, '2012-10-15 02:00:00'),
(1, '2012-10-17 02:00:00'),
(1, '2012-10-30 02:00:00'),
(1, '2012-10-31 02:00:00'),
(1, '2012-11-01 02:00:00'),
(1, '2012-11-02 02:00:00'),
(1, '2012-11-18 02:00:00'),
(1, '2012-11-19 02:00:00'),
(1, '2012-11-21 02:00:00'),
(1, '2012-11-25 02:00:00'),
(1, '2012-11-25 02:00:00'),
(1, '2012-11-26 02:00:00'),
(1, '2012-11-26 02:00:00'),
(1, '2012-11-24 02:00:00'),
(1, '2012-11-23 02:00:00'),
(1, '2012-11-28 02:00:00'),
(1, '2012-11-29 02:00:00'),
(1, '2012-11-30 02:00:00'),
(1, '2012-12-01 02:00:00'),
(1, '2012-12-02 02:00:00'),
(1, '2012-12-15 02:00:00'),
(1, '2012-12-17 02:00:00'),
(1, '2012-12-18 02:00:00'),
(1, '2012-12-19 02:00:00'),
(1, '2012-12-21 02:00:00'),
(1, '2012-12-25 02:00:00'),
(1, '2012-12-25 02:00:00'),
(1, '2012-12-26 02:00:00'),
(1, '2012-12-26 02:00:00'),
(1, '2012-12-24 02:00:00'),
(1, '2012-12-23 02:00:00'),
(1, '2012-12-31 02:00:00'),
(1, '2012-12-30 02:00:00'),
(1, '2012-12-28 02:00:00'),
(1, '2012-12-28 02:00:00'),
(1, '2012-12-30 02:00:00');
Và kết quả:
period starting period ending count(*)
2012-12-02 2012-12-31 17
2012-11-02 2012-12-01 14
2012-10-03 2012-11-01 5
điểm cuối chu kỳ được bao gồm.
Chơi với cái này trong SQL Fiddle .
Có một chút ngớ ngẩn tiềm ẩn ở chỗ bất kỳ khoảng thời gian 30 ngày nào không có hàng phù hợp sẽ không được đưa vào kết quả. Nếu bạn có thể tham gia điều này với một bảng các khoảng thời gian, điều đó có thể bị loại bỏ. Tuy nhiên, MySQL không có bất kỳ thứ gì giống như create_series () , vì vậy bạn phải xử lý nó trong ứng dụng của mình hoặc thử hack thông minh này .