Запит, щоб отримати всі рядки попереднього місяця


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 ваш запит не зовсім відповідає питанню, тоді як відповідь вище відповідає. Ваш повертає рядки між цим днем ​​минулого місяця та вчорашнім днем.
Matt Passell

@MattPassell Мені шкода, але betweenце включає межі .. Вона також включатиме поточну дату. Чому / як це буде обмежено вчора ?? Будь ласка, уточніть?
Ghazanfar Mir

4
Я розумію, що ти маєш на увазі .. Так ти маєш рацію .. мій запит не те, що хотів ОП .. Я неправильно зрозумів питання
Ghazanfar Mir

а як бути, якщо current_dateце не сьогодні, а випадкова дата, дана клієнтом?
dios231

22

Ось ще одна альтернатива. Якщо припустити, що у вас є індексоване поле DATEабо DATETIMEполе типу, для цього слід використовувати індекс, оскільки відформатовані дати будуть перетворені перед використанням індексу. Тоді ви повинні побачити rangeзапит, а не indexзапит при перегляді з 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. Набагато більше індексу. Ви також можете STR_TO_DATEрозкинути, DATE_FORMATщоб він завжди мав справу з датами.
Лі

14

Якщо немає майбутніх дат ...

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

Перевірено.


3
Думаю, вони шукали щось інше. тобто Усі записи минулого місяця (тобто 1 жовтня - 31 жовтня 2012 23:59:59). Наведений вище запит поверне останні ~ 30 днів із сьогоднішньої дати та часу .
Лі

13

Як варіант відповіді hobodave

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 як одиницю, отже, вам не знадобиться І, ось так:

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 день.
Грегг

На мою думку, це повинна бути прийнята відповідь, оскільки вона простіша за прийняту відповідь, але дає той самий результат
Grant

3

Незважаючи на те, що відповідь на це питання вже вибрано, я вважаю, що найпростіший запит буде

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

2
Ні, не зовсім. Дивіться мою відповідь на ваш коментар щодо відповіді, яку дав @hobodave
Matt Passell

@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),'%');

цей зможе скористатися перевагами індексу, якщо ваша дата_створена проіндексована, оскільки вона не застосовує жодної функції перетворення до значення поля.


@ggiroux - Однак, перед застосуванням LIKE, він повинен перетворити дату на тип символу.
martin clayton

так, справді, але все-таки покращення щодо обраної відповіді 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)

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

мені довелося зробити кілька змін, перевірте, працює це чи ні
sid busa
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.