Zapytanie, aby uzyskać wszystkie wiersze z poprzedniego miesiąca

90

Muszę zaznaczyć wszystkie wiersze w mojej bazie danych, które zostały utworzone w zeszłym miesiącu.

Na przykład, jeśli bieżącym miesiącem jest styczeń, chcę zwrócić wszystkie wiersze utworzone w grudniu, jeśli miesiącem jest luty, chcę zwrócić wszystkie wiersze utworzone w styczniu. Mam date_createdkolumnę w mojej bazy danych, która zawiera wykaz dat tworzone w tym formacie: 2007-06-05 14:50:17.

lewisqic
źródło

Odpowiedzi:

198
SELECT * FROM table
WHERE YEAR(date_created) = YEAR(CURRENT_DATE - INTERVAL 1 MONTH)
AND MONTH(date_created) = MONTH(CURRENT_DATE - INTERVAL 1 MONTH)
hobodave
źródło
70
SELECT * FROM table WHERE date_created BETWEEN (CURRENT_DATE() - INTERVAL 1 MONTH) AND CURRENT_DATE();
Ghazanfar Mir
12
@GhazanfarMir Twoje zapytanie nie pasuje do pytania, podczas gdy powyższa odpowiedź tak. Twój zwraca wiersze między tym dniem ostatniego miesiąca a wczoraj.
Matt Passell,
@MattPassell Przykro mi, ale betweenobejmuje granice .. Będzie zawierać również aktualną datę. Dlaczego / jak to będzie ograniczone do wczoraj ?? Proszę rozwinąć?
Ghazanfar Mir
4
Rozumiem, co masz na myśli .. Tak masz rację .. moje zapytanie nie jest to, co PO chciała .. I źle na pytanie
Ghazanfar Mir
a co jeśli current_dateto nie dzisiaj, a przypadkowa data podana przez klienta?
dios231
22

Oto inna alternatywa. Zakładając, że masz pole indeksowane DATElub DATETIMEpole typu, należy użyć indeksu, ponieważ sformatowane daty zostaną przekonwertowane na typ przed użyciem indeksu. Po wyświetleniu za pomocą EXPLAIN powinieneś zobaczyć rangezapytanie, a nie indexzapytanie .

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' )
Martin Clayton
źródło
+1. Znacznie bardziej przyjazny dla indeksów. Możesz także rzucić STR_TO_DATEwokół, DATE_FORMATwięc zawsze ma do czynienia z obiektami daty.
Leigh
14

Jeśli nie ma przyszłych dat ...

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

Przetestowany.

ekerner
źródło
3
Myślę, że szukali czegoś innego. tj. Wszystkie rekordy z ostatniego miesiąca (tj. 1 października - 31 października 2012 23:59:59). Powyższe zapytanie zwróci ostatnie ~ 30 dni od dzisiejszej daty i godziny .
Leigh,
13

Alternatywnie do odpowiedzi hobodave

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

Możesz osiągnąć to samo z EXTRACT, używając YEAR_MONTH jako jednostki, więc nie potrzebujesz AND, na przykład:

SELECT * FROM table
WHERE EXTRACT(YEAR_MONTH FROM date_created) = EXTRACT(YEAR_MONTH FROM CURDATE() - INTERVAL
1 MONTH)
SMTF
źródło
Działa to świetnie przez miesiące, ale niestety nie ma YEAR_WEEK odstępu czasowego , więc musiałbyś wrócić do odpowiedzi hobodave, jeśli potrzebujesz tygodni zamiast miesięcy.
Danny Beckett
8
SELECT *
FROM  yourtable
where DATE_FORMAT(date_created, '%Y-%m') = date_format(DATE_SUB(curdate(), INTERVAL 1 month),'%Y-%m')

Powinno to zwrócić wszystkie rekordy z poprzedniego miesiąca kalendarzowego, w przeciwieństwie do zapisów z ostatnich 30 lub 31 dni.

Gregg
źródło
Zapomniałem wspomnieć ... to powinno zwrócić wszystkie rekordy z poprzedniego miesiąca kalendarzowego, w przeciwieństwie do zapisów z ostatnich 30 lub 31 dni.
Gregg
Moim zdaniem powinna to być akceptowana odpowiedź, ponieważ jest prostsza niż zaakceptowana odpowiedź, ale daje ten sam wynik
Grant
3

Mimo że odpowiedź na to pytanie została już wybrana, wydaje mi się, że najprostsze będzie zapytanie

SELECT * 
FROM table 
WHERE 
date_created BETWEEN (CURRENT_DATE() - INTERVAL 1 MONTH) AND CURRENT_DATE();
Ghazanfar Mir
źródło
2
Nie, niezupełnie. Zobacz moją odpowiedź na Twój komentarz na temat odpowiedzi udzielonej przez @hobodave
Matt Passell
@MattPassell Masz rację, źle zrozumiałem pytanie .. Nie zrozumiałem, że wynik powinien ograniczać się tylko do rekordów TYLKO z zeszłego miesiąca.
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) 

To zadziałało dla mnie (wybiera wszystkie rekordy utworzone w zeszłym miesiącu, niezależnie od dnia uruchomienia zapytania w tym miesiącu)

Giles
źródło
1

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

ten będzie mógł skorzystać z indeksu, jeśli data_created jest indeksowana, ponieważ nie stosuje żadnej funkcji transformacji do wartości pola.

ggiroux
źródło
@ggiroux - Przed zastosowaniem LIKE musi jednak przekonwertować datę na typ znaku.
Martin Clayton
tak rzeczywiście, ale nadal poprawa w stosunku do wybranej odpowiedzi IMHO (indeksowany jest IFF date_created)
ggiroux
1

Oto zapytanie, aby uzyskać rekordy z ostatniego miesiąca:

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

Pozdrawiam - saqib

saqib jahangir Pakistan
źródło
Czy próbowałeś uruchomić to zapytanie? O ile widzę, nie zaznaczyłby wszystkich dat z poprzednich miesięcy (np .: dane zwrotne ze stycznia przez cały luty), ale zwróciłby dane z zakresu rozpoczynającego się tego samego dnia miesiąc temu
Nico Haase
0

Alternatywa z jednym warunkiem

SELECT * FROM table
WHERE YEAR(date_created) * 12 + MONTH(date_created)
    = YEAR(CURRENT_DATE) * 12 + MONTH(CURRENT_DATE) - 1
kcsoft
źródło
-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
źródło
Czy próbowałeś uruchomić to zapytanie? O ile widzę, nie zaznaczyłby wszystkich dat z poprzednich miesięcy (np .: dane zwrotne ze stycznia przez cały luty), ale zwróciłby dane z zakresu rozpoczynającego się tego samego dnia miesiąc temu
Nico Haase
dokonałem