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.

Odpowiedzi:


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

jest tym, czego chcesz.


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')

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";

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.


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;

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

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



1

użyj funkcji EXTRACT w ten sposób

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


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 ()


-2

Posługiwać się

GROUP BY year, month DESC";

Zamiast

GROUP BY MONTH(t.summaryDateTime) DESC";

chociaż wygląda na to, że GROUP BY MONTH (t.summaryDateTime) DESC z jakiegoś powodu nie porządkuje prawidłowo miesięcy ...
Derek Adair
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.