Raggruppa per mese e anno in MySQL


95

Data una tabella con un timestamp su ogni riga, come formatteresti la query per adattarla a questo specifico formato di oggetto json.

Sto cercando di organizzare un oggetto JSON in anni / mesi.

json per basare la query:

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

Ecco la domanda che ho finora:

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

La query si sta interrompendo perché (prevedibilmente) raggruppa i diversi anni.

Risposte:


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

è quello che vuoi.


60
+1: Un'altra alternativa che utilizza DATE_FORMAT :DATE_FORMAT(t.summaryDateTime, '%Y-%m')
OMG Ponies

3
Inoltre, FROM_UNIXTIME è necessario se hai un timestamp UNIX nel tuo DBDATE_FORMAT( FROM_UNIXTIME(t.summaryDateTime), '%Y-%m' )
Duncanmoo

Grazie @OMGPonies, con la tua sintassi sono in grado di eseguire GROUP BY condizionale.
Henry

Prestazioni ... il mio test di GROUP BY YEAR(date), MONTH(date) DESC;(~ 450 ms) e GROUP BY DATE_FORMAT(date,'%Y-%m')(~ 850 ms) su una tabella InnoDB con> 300.000 voci ha mostrato che il primo (la risposta contrassegnata a questa domanda) ha richiesto circa la metà del tempo rispetto al secondo.
ow3n

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

Benvenuto in StackOverflow! Questa è una domanda vecchia e già risolta. Saremo felici se potresti contribuire anche a domande più urgenti. Puoi trovare suggerimenti su come fornire buone risposte qui .
Mifeet

Vedi il mio commento sulla risposta sopra ... Sulle tabelle di grandi dimensioni questo metodo richiede il doppio del tempo.
ow3n

9

preferisco

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

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

Utilizzare DESC sia per YEAR che per il mese per ottenere l'ordine corretto.


7

So che questa è una vecchia domanda, ma quanto segue dovrebbe funzionare se non hai bisogno del nome del mese a livello di DB:

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

Vedere la documentazione della funzione EXTRACT

Probabilmente troverai che questo ha prestazioni migliori .. e se stai costruendo un oggetto JSON nel livello dell'applicazione, puoi eseguire la formattazione / ordinamento mentre esegui i risultati.

NB Non sapevo che potresti aggiungere DESC a una clausola GROUP BY in MySQL, forse ti manca una clausola 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
si prega di notare che l'output EXTRACT(YEAR_MONTH FROM summaryDateTime)è201901
Edgar Ortega

@EdgarOrtega Sì, ma dovrebbe essere sufficiente per generare l'oggetto JSON desiderato nella domanda originale utilizzando la logica dell'applicazione. Supponendo che una qualche forma di loop sul risultato della query sia già in corso, il mio approccio mira a ottenere le informazioni minime richieste dal DB nel modo più semplice e rapido possibile
Arth

1
Hai ragione, dovrebbe essere sufficiente. Il mio commento era solo per indicare come è l'output di quella funzione, forse a qualcuno non piace quel formato.
Edgar Ortega

@EdgarOrtega Nessun problema, grazie, un degno contributo!
Arth

2

Devi fare qualcosa del genere

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

Puoi farlo anche tu

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

ordinare per anno e mese. Diciamo che vuoi ordinare da quest'anno e questo mese fino a 12 mesi


1

usa la funzione ESTRATTA come questa

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

1

Ecco come lo faccio:

GROUP BY  EXTRACT(YEAR_MONTH FROM t.summaryDateTime);


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

Tuttavia, dovresti elaborarlo in uno script esterno per ottenere esattamente la struttura che stai cercando.

Ad esempio, usa l'esplosione di PHP per creare un array dall'elenco dei nomi dei mesi e quindi usa json_encode ()


-2

Uso

GROUP BY year, month DESC";

Invece di

GROUP BY MONTH(t.summaryDateTime) DESC";

anche se sembra che GROUP BY MONTH (t.summaryDateTime) DESC non ordina i mesi correttamente per qualche motivo ...
Derek Adair
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.