Grupo por mês e ano no MySQL


94

Dada uma tabela com um carimbo de data / hora em cada linha, como você formataria a consulta para caber neste formato de objeto json específico.

Estou tentando organizar um objeto json em anos / meses.

json para basear a consulta:

{
  "2009":["August","July","September"],
  "2010":["January", "February", "October"]
}

Aqui está a consulta que tenho até agora -

SELECT
    MONTHNAME(t.summaryDateTime) as month, YEAR(t.summaryDateTime) as year
FROM
    trading_summary t 
GROUP BY MONTH(t.summaryDateTime) DESC";

A consulta está se desfazendo porque (previsivelmente) agrupa os diferentes anos.

Respostas:


184
GROUP BY YEAR(t.summaryDateTime), MONTH(t.summaryDateTime) DESC;

é o que você quer.


60
+1: Outra alternativa usando DATE_FORMAT :DATE_FORMAT(t.summaryDateTime, '%Y-%m')
OMG Pôneis

3
Mais adiante, FROM_UNIXTIME é necessário se você tiver um carimbo de data / hora UNIX em seu banco de dadosDATE_FORMAT( FROM_UNIXTIME(t.summaryDateTime), '%Y-%m' )
Duncanmoo

Obrigado @OMGPonies, com sua sintaxe sou capaz de executar GROUP BY condicional.
Henry

Desempenho ... meu teste de GROUP BY YEAR(date), MONTH(date) DESC;(~ 450 ms) e GROUP BY DATE_FORMAT(date,'%Y-%m')(~ 850 ms) em uma tabela InnoDB com> 300.000 entradas mostrou que o primeiro (a resposta marcada para esta pergunta) levou cerca de metade do tempo que o último.
ow3n

77
GROUP BY DATE_FORMAT(summaryDateTime,'%Y-%m')

Bem-vindo ao StackOverflow! Esta é uma pergunta antiga e já respondida. Ficaremos felizes se você também puder contribuir com questões mais urgentes. Você pode encontrar dicas para fornecer boas respostas aqui .
Mifeet de

Veja meu comentário sobre a resposta acima ... Em tabelas grandes, esse método leva o dobro do tempo.
3 de

8
SELECT MONTHNAME(t.summaryDateTime) as month, YEAR(t.summaryDateTime) as year
FROM trading_summary t
GROUP BY YEAR(t.summaryDateTime) DESC, MONTH(t.summaryDateTime) DESC

Deve usar DESC para YEAR e Month para obter a ordem correta.


8

eu prefiro

SELECT
    MONTHNAME(t.summaryDateTime) as month, YEAR(t.summaryDateTime) as year
FROM
    trading_summary t 
GROUP BY EXTRACT(YEAR_MONTH FROM t.summaryDateTime) DESC";

6

Eu sei que esta é uma pergunta antiga, mas o seguinte deve funcionar se você não precisar do nome do mês no nível do banco de dados:

  SELECT EXTRACT(YEAR_MONTH FROM summaryDateTime) summary_year_month 
    FROM trading_summary  
GROUP BY summary_year_month;

Veja a documentação da função EXTRACT

Você provavelmente achará que este tem um desempenho melhor .. e se estiver construindo um objeto JSON na camada do aplicativo, você pode fazer a formatação / ordenação à medida que executa os resultados.

NB, eu não sabia que você poderia adicionar DESC a uma cláusula GROUP BY no MySQL, talvez esteja faltando uma cláusula ORDER BY:

  SELECT EXTRACT(YEAR_MONTH FROM summaryDateTime) summary_year_month 
    FROM trading_summary  
GROUP BY summary_year_month
ORDER BY summary_year_month DESC;

1
observe que a saída de EXTRACT(YEAR_MONTH FROM summaryDateTime)é201901
Edgar Ortega

@EdgarOrtega Sim, mas isso deve ser o suficiente para gerar o objeto JSON desejado na questão original usando a lógica do aplicativo. Supondo que alguma forma de loop no resultado da consulta já esteja acontecendo, minha abordagem visa obter o mínimo de informações necessárias do banco de dados da maneira mais simples e rápida possível
Dia

1
Você está certo, isso deve ser o suficiente. Meu comentário foi apenas para indicar como é a saída dessa função, talvez alguém não goste desse formato.
Edgar Ortega

@EdgarOrtega Não se preocupe, obrigado, uma contribuição valiosa!
Dia

2

Você deve fazer algo assim

SELECT onDay, id, 
sum(pxLow)/count(*),sum(pxLow),count(`*`),
CONCAT(YEAR(onDay),"-",MONTH(onDay)) as sdate 
FROM ... where stockParent_id =16120 group by sdate order by onDay

2

Você também pode fazer isso

SELECT  SUM(amnt) `value`,DATE_FORMAT(dtrg,'%m-%y') AS label FROM rentpay GROUP BY YEAR(dtrg) DESC, MONTH(dtrg) DESC LIMIT 12

para solicitar por ano e mês. Digamos que você queira fazer o pedido deste ano e deste mês até os 12 meses


1

use a função EXTRACT como esta

mysql> SELECT EXTRACT(YEAR FROM '2009-07-02');
       -> 2009

0

Você está agrupando por mês apenas, você deve adicionar YEAR () ao grupo por


0
SELECT YEAR(t.summaryDateTime) as yr, GROUP_CONCAT(MONTHNAME(t.summaryDateTime)) AS month 
FROM trading_summary t GROUP BY yr

Ainda assim, você precisaria processá-lo em um script externo para obter exatamente a estrutura que está procurando.

Por exemplo, use o explode do PHP para criar um array da lista de nomes de meses e, em seguida, use json_encode ()


0

É assim que eu faço:

GROUP BY  EXTRACT(YEAR_MONTH FROM t.summaryDateTime);

-2

Usar

GROUP BY year, month DESC";

Ao invés de

GROUP BY MONTH(t.summaryDateTime) DESC";

embora pareça que GROUP BY MONTH (t.summaryDateTime) DESC não ordena os meses corretamente por algum motivo ...
Derek Adair
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.