Gruppieren Sie nach Monat und Jahr in MySQL

94

Wie würden Sie bei einer Tabelle mit einem Zeitstempel in jeder Zeile die Abfrage so formatieren, dass sie in dieses bestimmte JSON-Objektformat passt?

Ich versuche, ein JSON-Objekt in Jahre / Monate zu organisieren.

json, um die Abfrage zu begründen:

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

Hier ist die Frage, die ich bisher habe -

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

Die Abfrage bricht zusammen, weil sie (vorhersehbar) die verschiedenen Jahre zusammenfasst.

Derek Adair
quelle

Antworten:

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

ist was du willst.

Mitch Dempsey
quelle
60
+1: Eine andere Alternative mit DATE_FORMAT :DATE_FORMAT(t.summaryDateTime, '%Y-%m')
OMG Ponys
3
Darüber hinaus wird FROM_UNIXTIME benötigt, wenn Sie einen UNIX-Zeitstempel in Ihrer DB habenDATE_FORMAT( FROM_UNIXTIME(t.summaryDateTime), '%Y-%m' )
Duncanmoo
Danke @OMGPonies, mit Ihrer Syntax kann ich bedingte GROUP BY ausführen.
Henry
Leistung ... Mein Test von GROUP BY YEAR(date), MONTH(date) DESC;(~ 450 ms) und GROUP BY DATE_FORMAT(date,'%Y-%m')(~ 850 ms) an einer InnoDB-Tabelle mit> 300.000 Einträgen ergab, dass Ersteres (die markierte Antwort auf diese Frage) ~ die Hälfte der Zeit in Anspruch nahm.
Ow3n
76
GROUP BY DATE_FORMAT(summaryDateTime,'%Y-%m')
Ferhat KOÇER
quelle
Willkommen bei StackOverflow! Dies ist eine alte und bereits beantwortete Frage. Wir würden uns freuen, wenn Sie auch zu dringlicheren Fragen beitragen könnten. Tipps zu guten Antworten finden Sie hier .
Mifeet
Siehe meinen Kommentar zur obigen Antwort ... Bei großen Tabellen dauert diese Methode doppelt so lange.
Ow3n
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

Sollte DESC sowohl für JAHR als auch für Monat verwenden, um die richtige Reihenfolge zu erhalten.

Sasindu H.
quelle
7

ich bevorzuge

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

Ich weiß, dass dies eine alte Frage ist, aber Folgendes sollte funktionieren, wenn Sie den Monatsnamen auf DB-Ebene nicht benötigen:

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

Siehe EXTRACT-Funktionsdokumente

Sie werden wahrscheinlich feststellen, dass dies eine bessere Leistung aufweist. Wenn Sie ein JSON-Objekt in der Anwendungsschicht erstellen, können Sie die Formatierung / Reihenfolge vornehmen, während Sie die Ergebnisse durchgehen.

NB Ich wusste nicht, dass Sie DESC zu einer GROUP BY-Klausel in MySQL hinzufügen können. Vielleicht fehlt Ihnen eine ORDER BY-Klausel:

  SELECT EXTRACT(YEAR_MONTH FROM summaryDateTime) summary_year_month 
    FROM trading_summary  
GROUP BY summary_year_month
ORDER BY summary_year_month DESC;
Arth
quelle
1
Bitte beachten Sie, dass die Ausgabe von EXTRACT(YEAR_MONTH FROM summaryDateTime)ist201901
Edgar Ortega
@EdgarOrtega Ja, aber das sollte ausreichen, um das gewünschte JSON-Objekt in der ursprünglichen Frage mithilfe der Anwendungslogik zu generieren. Unter der Annahme, dass bereits eine Form der Schleife über das Abfrageergebnis stattfindet, zielt mein Ansatz darauf ab, die minimal erforderlichen Informationen so einfach und schnell wie möglich von der DB zu erhalten
Arth
1
Du hast recht, das sollte reichen. Mein Kommentar war nur, um anzuzeigen, wie die Ausgabe dieser Funktion ist, vielleicht mag jemand dieses Format nicht.
Edgar Ortega
@EdgarOrtega Keine Sorge, danke, ein würdiger Beitrag!
Arth
2

Sie müssen so etwas tun

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
michal
quelle
2

Sie können dies auch tun

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

nach Jahr und Monat zu bestellen. Nehmen wir an, Sie möchten ab diesem Jahr und diesem Monat bis zu 12 Monaten bestellen

Niclausel
quelle
1

Verwenden Sie die EXTRACT-Funktion wie folgt

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

Sie gruppieren nur nach Monat, Sie müssen YEAR () zur Gruppe nach hinzufügen

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

Trotzdem müssten Sie es in einem externen Skript verarbeiten, um genau die Struktur zu erhalten, nach der Sie suchen.

Verwenden Sie beispielsweise die Explosion von PHP, um ein Array aus der Liste der Monatsnamen zu erstellen, und verwenden Sie dann json_encode ()

Mchl
quelle
0

So mache ich es:

GROUP BY  EXTRACT(YEAR_MONTH FROM t.summaryDateTime);
CTBrewski
quelle
-2

Verwenden

GROUP BY year, month DESC";

Anstatt

GROUP BY MONTH(t.summaryDateTime) DESC";
Kyra
quelle
obwohl es scheint, dass GROUP BY MONTH (t.summaryDateTime) DESC die Monate aus irgendeinem Grund nicht richtig bestellt ...
Derek Adair