Запрос на получение всех строк за предыдущий месяц


90

Мне нужно выбрать все строки в моей базе данных, которые были созданы в прошлом месяце.

Например, если текущий месяц - январь, тогда я хочу вернуть все строки, созданные в декабре, если месяц февраль, то я хочу вернуть все строки, созданные в январе. У меня есть date_createdстолбец в моей базе данных , которая содержит список дат , созданные в этом формате: 2007-06-05 14:50:17.

Ответы:


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 ваш запрос не совсем соответствует вопросу, тогда как ответ выше соответствует. Ваш возвращает строки с этого дня в прошлом месяце по вчерашний день.
Мэтт Пасселл

@MattPassell Извините, но betweenвключает границы .. Он также будет включать текущую дату. Почему / как ограничится вчера ?? Пожалуйста, дополните?
Ghazanfar Mir

4
Я понимаю, что вы имеете в виду .. Да, вы правы .. мой запрос не то, что хотел OP .. Я неправильно понял вопрос
Ghazanfar Mir

а если current_dateэто не сегодня, а случайная дата, полученная от клиента?
dios231

22

Вот еще одна альтернатива. Предполагая, что у вас есть индексированное поле DATEили DATETIMEполе типа, при этом следует использовать индекс, поскольку форматированные даты будут преобразованы в тип перед использованием индекса. После этого при просмотре с EXPLAIN вы должны увидеть rangeзапрос, а не indexзапрос .

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. Намного более удобен для индексации. Вы также можете бросить STR_TO_DATEвокруг, DATE_FORMATчтобы он всегда имел дело с объектами даты.
Leigh

14

Если нет будущих дат ...

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

Проверено.


3
Я думаю, они искали чего-то другого. т.е. все записи за последний месяц (т.е. 1 октября - 31 октября 2012 г., 23:59:59). Приведенный выше запрос вернет последние ~ 30 дней или около того с сегодняшней даты и времени .
Leigh

13

В качестве альтернативы ответу Хободаве

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

Вы можете добиться того же с EXTRACT, используя YEAR_MONTH в качестве единицы, поэтому вам не понадобится AND, например:

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

Это отлично работает в течение нескольких месяцев, но, к сожалению, нет YEAR_WEEK временного интервала , поэтому вам придется вернуться к ответу hobodave, если вам нужны недели вместо месяцев.
Дэнни Беккет

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

Это должно вернуть все записи за предыдущий календарный месяц, в отличие от записей за последние 30 или 31 день.


Я забыл упомянуть ... это должно вернуть все записи за предыдущий календарный месяц, в отличие от записей за последние 30 или 31 день.
Gregg

На мой взгляд, это должен быть принятый ответ, поскольку он проще, чем принятый ответ, но дает тот же результат
Грант

3

Несмотря на то, что ответ на этот вопрос уже выбран, я считаю, что самым простым запросом будет

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

2
Нет, не совсем так. См. Мой ответ на ваш комментарий к ответу @hobodave
Мэтт Пасселл

@MattPassell Вы правы, я неправильно понял вопрос .. Я упустил момент, что результат должен быть ограничен только записями ТОЛЬКО за последний месяц.
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) 

Это сработало для меня (выбирает все записи, созданные за последний месяц, независимо от дня, когда вы запускаете запрос в этом месяце)


1

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

этот сможет воспользоваться преимуществом индекса, если ваш date_created проиндексирован, потому что он не применяет никаких функций преобразования к значению поля.


@ggiroux - он должен преобразовать дату в тип символа, прежде чем применять LIKE.
Мартин Клейтон

да, действительно, но все же улучшение по сравнению с выбранным ответом IMHO (IFF date_created проиндексировано)
ggiroux

1

Вот запрос, чтобы получить записи за последний месяц:

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

С уважением - saqib


Вы пробовали выполнить этот запрос? Насколько я понимаю, он не будет выбирать все даты за предыдущие месяцы (например: возвращать данные за январь на протяжении всего февраля), но возвращает данные из диапазона, начиная с того же дня месяц назад
Нико Хаасе,

0

Альтернатива с одним условием

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)

Вы пробовали выполнить этот запрос? Насколько я понимаю, он не будет выбирать все даты за предыдущие месяцы (например: возвращать данные с января на протяжении всего февраля), но возвращает данные из диапазона, начиная с того же дня месяц назад
Нико Хаасе,

Мне пришлось внести несколько изменений, проверьте, работает он или нет
Сид Буса
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.