Grupuj według miesiąca i roku w MySQL

98

Biorąc pod uwagę tabelę z sygnaturą czasową w każdym wierszu, jak sformatować zapytanie, aby pasowało do tego konkretnego formatu obiektu json.

Próbuję uporządkować obiekt json w lata / miesiące.

json, aby oprzeć zapytanie na:

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

Oto zapytanie, które mam do tej pory -

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

Kwerenda się psuje, ponieważ (w sposób przewidywalny) gromadzi się w różnych latach.

Derek Adair
źródło

Odpowiedzi:

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

jest tym, czego chcesz.

Mitch Dempsey
źródło
62
+1: Inna alternatywa przy użyciu DATE_FORMAT :DATE_FORMAT(t.summaryDateTime, '%Y-%m')
OMG Kucyki
3
Co więcej, FROM_UNIXTIME jest potrzebny, jeśli masz znacznik czasu UNIX w swojej DATE_FORMAT( FROM_UNIXTIME(t.summaryDateTime), '%Y-%m' )
bazie danych
Dzięki @OMGPonies, dzięki twojej składni jestem w stanie wykonać warunkowe GROUP BY.
Henry
Wydajność ... mój test GROUP BY YEAR(date), MONTH(date) DESC;(~ 450 ms) i GROUP BY DATE_FORMAT(date,'%Y-%m')(~ 850 ms) na tabeli InnoDB z> 300 000 wpisów wykazał, że pierwsza (zaznaczona odpowiedź na to pytanie) zajęła około połowę czasu niż druga.
ow3n
78
GROUP BY DATE_FORMAT(summaryDateTime,'%Y-%m')
Ferhat KOÇER
źródło
Witamy w StackOverflow! To jest stare pytanie, na które udzielono już odpowiedzi. Będzie nam miło, jeśli będziesz mógł przyczynić się do bardziej palących pytań. Można znaleźć wskazówki na zapewnienie dobrych odpowiedzi tutaj .
Mifeet
Zobacz mój komentarz do odpowiedzi powyżej ... Na dużych stołach ta metoda zajmuje dwa razy dłużej.
ow3n
9

wolę

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
źródło
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

Aby uzyskać prawidłową kolejność, należy używać DESC zarówno dla ROKU, jak i miesiąca.

Sasindu H.
źródło
7

Wiem, że to stare pytanie, ale jeśli nie potrzebujesz nazwy miesiąca na poziomie bazy danych, poniższe powinno zadziałać:

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

Zobacz dokumentację funkcji EXTRACT

Prawdopodobnie okaże się, że jest to bardziej wydajne ... a jeśli tworzysz obiekt JSON w warstwie aplikacji, możesz wykonać formatowanie / porządkowanie podczas przeglądania wyników.

NB nie wiedziałem, że możesz dodać DESC do klauzuli GROUP BY w MySQL, być może brakuje Ci klauzuli 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;
Arth
źródło
1
Proszę pamiętać, że wyjście z EXTRACT(YEAR_MONTH FROM summaryDateTime)jest201901
Edgar Ortega
@EdgarOrtega Tak, ale to powinno wystarczyć do wygenerowania żądanego obiektu JSON w pierwotnym pytaniu przy użyciu logiki aplikacji. Zakładając, że jakaś forma zapętlenia wyniku zapytania już się dzieje, moje podejście ma na celu uzyskanie minimum wymaganych informacji z bazy danych tak prosto i szybko, jak to możliwe
Arth
1
Masz rację, to powinno wystarczyć. Mój komentarz miał na celu tylko wskazanie, jak wygląda wyjście z tej funkcji, może komuś ten format nie odpowiada.
Edgar Ortega
@EdgarOrtega Bez obaw, dzięki, godny wkład!
Arth
2

Musisz zrobić coś takiego

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
źródło
2

Ty też to zrób

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

zamawiać według roku i miesiąca. Powiedzmy, że chcesz zamawiać od tego roku i tego miesiąca aż do 12 miesiąca

Niclausel
źródło
1

Grupujesz tylko według miesiąca, musisz dodać ROK () do grupy według

Eduardo Rascon
źródło
1

użyj funkcji EXTRACT w ten sposób

mysql> SELECT EXTRACT(YEAR FROM '2009-07-02');
       -> 2009
rebaimelek
źródło
1

Oto jak to robię:

GROUP BY  EXTRACT(YEAR_MONTH FROM t.summaryDateTime);
CTBrewski
źródło
0
SELECT YEAR(t.summaryDateTime) as yr, GROUP_CONCAT(MONTHNAME(t.summaryDateTime)) AS month 
FROM trading_summary t GROUP BY yr

Nadal musisz przetworzyć to w zewnętrznym skrypcie, aby uzyskać dokładnie taką strukturę, której szukasz.

Na przykład użyj funkcji eksplodowania PHP, aby utworzyć tablicę z listy nazw miesięcy, a następnie użyj json_encode ()

Mchl
źródło
-2

Posługiwać się

GROUP BY year, month DESC";

Zamiast

GROUP BY MONTH(t.summaryDateTime) DESC";
Kyra
źródło
chociaż wygląda na to, że GROUP BY MONTH (t.summaryDateTime) DESC z jakiegoś powodu nie porządkuje prawidłowo miesięcy ...
Derek Adair