Consulta para obter todas as linhas do mês anterior

92

Preciso selecionar todas as linhas em meu banco de dados que foram criadas no mês passado.

Por exemplo, se o mês atual for janeiro, desejo retornar todas as linhas que foram criadas em dezembro, se o mês for fevereiro, desejo retornar todas as linhas criadas em janeiro. Eu tenho uma date_createdcoluna no meu banco de dados que relaciona a data criado neste formato: 2007-06-05 14:50:17.

lewisqic
fonte

Respostas:

202
SELECT * FROM table
WHERE YEAR(date_created) = YEAR(CURRENT_DATE - INTERVAL 1 MONTH)
AND MONTH(date_created) = MONTH(CURRENT_DATE - INTERVAL 1 MONTH)
hobodave
fonte
70
SELECT * FROM table WHERE date_created BETWEEN (CURRENT_DATE() - INTERVAL 1 MONTH) AND CURRENT_DATE();
Ghazanfar Mir
12
@GhazanfarMir sua consulta não corresponde exatamente à pergunta, enquanto a resposta acima sim. Yours retorna as linhas entre este dia do mês passado e ontem.
Matt Passell
@MattPassell Lamento, mas betweeninclui os limites. Incluirá também a data atual. Por que / como será limitado ao ontem ?? Por favor elabore?
Ghazanfar Mir
5
Entendo o que você quer dizer .. Sim, você está certo .. minha pergunta não é o que o OP queria .. Eu entendi mal a pergunta
Ghazanfar Mir
e se current_datenão for hoje, mas uma data aleatória fornecida pelo cliente?
dios231
23

Aqui está outra alternativa. Supondo que você tenha um campo indexado DATEou de DATETIMEtipo, isso deve usar o índice, pois as datas formatadas serão convertidas por tipo antes de o índice ser usado. Você deve ver uma rangeconsulta em vez de uma indexconsulta quando visualizada com 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' )
martin clayton
fonte
+1. Muito mais amigável ao índice. Você também pode lançar um em STR_TO_DATEtorno do DATE_FORMATpara que ele esteja sempre lidando com objetos de data.
Leigh
15

Se não houver datas futuras ...

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

Testado.

Ekerner
fonte
3
Acho que eles estavam procurando por algo diferente. ou seja, todos os registros do mês passado (ou seja, 1º de outubro - 31 de outubro de 2012 23:59:59). A consulta acima retornaria os últimos aproximadamente 30 dias, a partir da data e hora de hoje .
Leigh
13

Alternativamente à resposta do hobodave

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

Você poderia conseguir o mesmo com EXTRACT, usando YEAR_MONTH como unidade, portanto, você não precisaria do AND, assim:

SELECT * FROM table
WHERE EXTRACT(YEAR_MONTH FROM date_created) = EXTRACT(YEAR_MONTH FROM CURDATE() - INTERVAL
1 MONTH)
SMTF
fonte
Isso funciona muito bem por meses, mas infelizmente não há YEAR_WEEK intervalo temporal , então você terá que voltar à resposta do hobodave se precisar de semanas em vez de meses.
Danny Beckett
8
SELECT *
FROM  yourtable
where DATE_FORMAT(date_created, '%Y-%m') = date_format(DATE_SUB(curdate(), INTERVAL 1 month),'%Y-%m')

Isso deve retornar todos os registros do mês anterior, em oposição aos registros dos últimos 30 ou 31 dias.

Gregg
fonte
Esqueci de mencionar ... isso deve retornar todos os registros do mês anterior, ao contrário dos registros dos últimos 30 ou 31 dias.
Gregg,
Na minha opinião, esta deve ser a resposta aceita, pois é mais simples do que a resposta aceita, mas fornece o mesmo resultado
Grant,
3

Embora a resposta para esta pergunta já tenha sido selecionada, no entanto, acredito que a consulta mais simples será

SELECT * 
FROM table 
WHERE 
date_created BETWEEN (CURRENT_DATE() - INTERVAL 1 MONTH) AND CURRENT_DATE();
Ghazanfar Mir
fonte
2
Não, não exatamente. Veja minha resposta ao seu comentário sobre a resposta dada por @hobodave
Matt Passell
@MattPassell Você está certo, eu entendi mal a pergunta .. Eu perdi o ponto que o resultado deve ser limitado apenas aos registros do mês passado.
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) 

Isso funcionou para mim (seleciona todos os registros criados no mês passado, independentemente do dia em que você executa a consulta neste mês)

Giles
fonte
1

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

este poderá tirar proveito de um índice se o seu date_created estiver indexado, pois não aplica nenhuma função de transformação ao valor do campo.

ggiroux
fonte
@ggiroux - No entanto, ele tem que converter a data em um tipo de caractere antes de aplicar o LIKE.
Martin Clayton
sim, de fato, mas ainda uma melhoria em relação à resposta selecionada IMHO (IFF date_created is indexed)
ggiroux
1

Aqui está a consulta para obter os registros do último mês:

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

Atenciosamente - saqib

saqib jahangir Paquistão
fonte
Você já tentou executar essa consulta? Pelo que vejo, ele não selecionaria todas as datas dos meses anteriores (como em: retornar dados de janeiro a fevereiro inteiro), mas retornaria dados de um intervalo começando no mesmo dia um mês atrás
Nico Haase
0

Alternativa com condição única

SELECT * FROM table
WHERE YEAR(date_created) * 12 + MONTH(date_created)
    = YEAR(CURRENT_DATE) * 12 + MONTH(CURRENT_DATE) - 1
kcsoft
fonte
-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
fonte
Você já tentou executar essa consulta? Pelo que vejo, ele não selecionaria todas as datas dos meses anteriores (como em: retornar dados de janeiro a todo o fevereiro), mas retornaria dados de um intervalo começando no mesmo dia um mês atrás
Nico Haase
Fiz