Truy vấn để lấy tất cả các hàng từ tháng trước


90

Tôi cần chọn tất cả các hàng trong cơ sở dữ liệu của mình đã được tạo vào tháng trước.

Ví dụ: nếu tháng hiện tại là tháng Giêng, thì tôi muốn trả lại tất cả các hàng đã được tạo vào tháng Mười Hai, nếu tháng là tháng Hai, thì tôi muốn trả lại tất cả các hàng đã được tạo trong tháng Giêng. Tôi có một date_createdcột trong cơ sở dữ liệu của tôi rằng liệt kê các ngày tạo ở định dạng này: 2007-06-05 14:50:17.

Câu trả lời:


198
SELECT * FROM table
WHERE YEAR(date_created) = YEAR(CURRENT_DATE - INTERVAL 1 MONTH)
AND MONTH(date_created) = MONTH(CURRENT_DATE - INTERVAL 1 MONTH)

70
SELECT * FROM table WHERE date_created BETWEEN (CURRENT_DATE() - INTERVAL 1 MONTH) AND CURRENT_DATE();
Ghazanfar Mir

12
@GhazanfarMir truy vấn của bạn không hoàn toàn phù hợp với câu hỏi, trong khi câu trả lời ở trên thì đúng. Của bạn trả về các hàng từ ngày này tháng trước đến ngày hôm qua.
Matt Passell

@MattPassell Tôi xin lỗi nhưng đã betweenbao gồm các ranh giới .. Nó cũng sẽ bao gồm cả ngày hiện tại. Tại sao / Làm thế nào nó sẽ được giới hạn đến ngày hôm qua ?? Xin hãy giải thích?
Ghazanfar Mir,

4
Tôi xem những gì bạn có nghĩa là .. Có bạn là đúng .. truy vấn của tôi không phải là những gì OP muốn .. Tôi hiểu lầm câu hỏi
Ghazanfar Mir

Còn nếu current_dateđó không phải là ngày hôm nay mà là một ngày ngẫu nhiên do khách hàng đưa ra?
dios231

22

Đây là một giải pháp thay thế khác. Giả sử bạn có trường kiểu DATEhoặc DATETIMEtrường được lập chỉ mục , trường này sẽ sử dụng chỉ mục vì ngày tháng được định dạng sẽ được chuyển đổi kiểu trước khi chỉ mục được sử dụng. Sau đó, bạn sẽ thấy một rangetruy vấn thay vì một indextruy vấn khi được xem với EXPLAIN .

SELECT
    * 
FROM
    table
WHERE 
    date_created >= DATE_FORMAT( CURRENT_DATE - INTERVAL 1 MONTH, '%Y/%m/01' ) 
AND
    date_created < DATE_FORMAT( CURRENT_DATE, '%Y/%m/01' )

+1. Chỉ số thân thiện hơn nhiều. Bạn cũng có thể ném STR_TO_DATExung quanh DATE_FORMATđể nó luôn xử lý các đối tượng ngày tháng.
Leigh

14

Nếu không có ngày trong tương lai ...

SELECT * 
FROM   table_name 
WHERE  date_created > (NOW() - INTERVAL 1 MONTH);

Thử nghiệm.


3
Tôi nghĩ họ đang tìm kiếm một cái gì đó khác biệt. tức là Tất cả các bản ghi từ tháng trước (tức là ngày 1 tháng 10 - ngày 31 tháng 10 năm 2012 23:59:59). Truy vấn ở trên sẽ trả về ~ 30 ngày qua hoặc lâu hơn, kể từ ngày và giờ hôm nay .
Leigh

13

Thay vào đó là câu trả lời của hobodave

SELECT * FROM table
WHERE YEAR(date_created) = YEAR(CURRENT_DATE - INTERVAL 1 MONTH)
AND MONTH(date_created) = MONTH(CURRENT_DATE - INTERVAL 1 MONTH)

Bạn có thể đạt được điều tương tự với EXTRACT, sử dụng YEAR_MONTH làm đơn vị, do đó bạn sẽ không cần AND, như sau:

SELECT * FROM table
WHERE EXTRACT(YEAR_MONTH FROM date_created) = EXTRACT(YEAR_MONTH FROM CURDATE() - INTERVAL
1 MONTH)

Điều này hoạt động tốt trong nhiều tháng, nhưng không may là không có YEAR_WEEK khoảng thời gian , vì vậy bạn phải quay lại câu trả lời của hobodave nếu bạn cần vài tuần thay vì vài tháng.
Danny Beckett

8
SELECT *
FROM  yourtable
where DATE_FORMAT(date_created, '%Y-%m') = date_format(DATE_SUB(curdate(), INTERVAL 1 month),'%Y-%m')

Điều này sẽ trả về tất cả các bản ghi từ tháng trước đó, trái ngược với các bản ghi trong 30 hoặc 31 ngày qua.


Tôi quên đề cập ... điều này sẽ trả lại tất cả các bản ghi từ tháng trước, trái ngược với các bản ghi trong 30 hoặc 31 ngày qua.
Gregg

Theo tôi đây sẽ là câu trả lời được chấp nhận vì nó là đơn giản hơn so với các câu trả lời được chấp nhận chưa cung cấp hiệu quả tương tự
Grant

3

Mặc dù câu trả lời cho câu hỏi này đã được chọn, tuy nhiên, tôi tin rằng truy vấn đơn giản nhất sẽ là

SELECT * 
FROM table 
WHERE 
date_created BETWEEN (CURRENT_DATE() - INTERVAL 1 MONTH) AND CURRENT_DATE();

2
Không, không hoàn toàn. Xem phản ứng của tôi để xét của bạn về câu trả lời được đưa ra bởi @hobodave
Matt Passell

@MattPassell Bạn nói đúng, tôi đã hiểu sai câu hỏi .. Tôi đã bỏ sót điểm rằng kết quả chỉ nên giới hạn cho các bản ghi DUY NHẤT từ tháng trước.
Ghazanfar Mir,

2
WHERE created_date >= DATE_ADD(LAST_DAY(DATE_SUB(NOW(), INTERVAL 2 MONTH)), INTERVAL 1 DAY) 
  AND created_date <= DATE_ADD(LAST_DAY(DATE_SUB(NOW(), INTERVAL 1 MONTH)), INTERVAL 0 DAY) 

Điều này phù hợp với tôi (Chọn tất cả các bản ghi được tạo từ tháng trước, bất kể ngày bạn chạy truy vấn trong tháng này)


1

select fields FROM table WHERE date_created LIKE concat(LEFT(DATE_SUB(NOW(), interval 1 month),7),'%');

cái này sẽ có thể tận dụng chỉ mục nếu date_create của bạn được lập chỉ mục, bởi vì nó không áp dụng bất kỳ hàm chuyển đổi nào cho giá trị trường.


@ggiroux - Nó phải chuyển đổi ngày tháng sang kiểu ký tự trước khi áp dụng LIKE.
martin clayton

Có thực sự, nhưng vẫn còn một sự cải tiến so với câu trả lời IMHO chọn (IFF date_created được lập chỉ mục)
ggiroux

1

Đây là truy vấn để lấy các bản ghi của tháng trước:

SELECT *
FROM `tablename`
WHERE `datefiled`
BETWEEN DATE_SUB( DATE( NOW( ) ) , INTERVAL 1
MONTH )
AND 
LAST_DAY( DATE_SUB( DATE( NOW( ) ) , INTERVAL 1
MONTH ) )

Trân trọng - saqib


Bạn đã thử chạy truy vấn đó chưa? Theo như tôi thấy, nó sẽ không chọn tất cả các ngày từ các tháng trước (như trong: trả về dữ liệu từ tháng 1 trong suốt cả tháng 2), nhưng trả lại dữ liệu từ một phạm vi bắt đầu từ cùng ngày một tháng trước
Nico Haase

0

Thay thế với điều kiện duy nhất

SELECT * FROM table
WHERE YEAR(date_created) * 12 + MONTH(date_created)
    = YEAR(CURRENT_DATE) * 12 + MONTH(CURRENT_DATE) - 1

-1
SELECT *  FROM table  
WHERE  YEAR(date_created) = YEAR(CURRENT_DATE - INTERVAL 1 MONTH)
AND MONTH(date_created) = MONTH(CURRENT_DATE - INTERVAL 1 MONTH)

Bạn đã thử chạy truy vấn đó chưa? Theo như tôi thấy, nó sẽ không chọn tất cả các ngày từ các tháng trước (như trong: trả về dữ liệu từ tháng 1 trong suốt cả tháng 2), nhưng trả lại dữ liệu từ một phạm vi bắt đầu từ cùng ngày một tháng trước
Nico Haase

tôi đã thực hiện một số thay đổi, hãy kiểm tra xem nó hoạt động hay không
sid busa
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.