Agrupar por mes y año en MySQL

95

Dada una tabla con una marca de tiempo en cada fila, ¿cómo formatearía la consulta para que se ajuste a este formato de objeto json específico?

Estoy tratando de organizar un objeto json en años / meses.

json para basar la consulta en:

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

Aquí está la consulta que tengo hasta ahora:

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

La consulta se está descomponiendo porque (como era de esperar) agrupa los diferentes años.

Derek Adair
fuente

Respuestas:

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

es lo que quieres.

Mitch Dempsey
fuente
60
+1: Otra alternativa con DATE_FORMAT :DATE_FORMAT(t.summaryDateTime, '%Y-%m')
OMG Ponies
3
Además, se necesita FROM_UNIXTIME si tiene una marca de tiempo UNIX en su base de datosDATE_FORMAT( FROM_UNIXTIME(t.summaryDateTime), '%Y-%m' )
Duncanmoo
Gracias @OMGPonies, con tu sintaxis puedo realizar GROUP BY condicional.
Henry
Rendimiento ... mi prueba de GROUP BY YEAR(date), MONTH(date) DESC;(~ 450 ms) y GROUP BY DATE_FORMAT(date,'%Y-%m')(~ 850 ms) en una tabla InnoDB con> 300,000 entradas mostró que la primera (la respuesta marcada a esta pregunta) tomó ~ la mitad del tiempo que la última.
ow3n
77
GROUP BY DATE_FORMAT(summaryDateTime,'%Y-%m')
Ferhat KOÇER
fuente
¡Bienvenido a StackOverflow! Esta es una pregunta antigua y ya respondida. Estaremos felices si usted también pudiera contribuir con preguntas más urgentes Puede encontrar consejos sobre cómo proporcionar buenas respuestas aquí .
Mifeet
Vea mi comentario sobre la respuesta anterior ... En tablas de gran tamaño, este método tarda el doble.
ow3n
9

yo prefiero

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
fuente
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

Debe usar DESC para AÑO y Mes para obtener el orden correcto.

Sasindu H
fuente
7

Sé que esta es una pregunta antigua, pero lo siguiente debería funcionar si no necesita el nombre del mes en el nivel de base de datos:

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

Ver los documentos de la función EXTRACCIÓN

Probablemente encontrará que esto tiene un mejor rendimiento ... y si está creando un objeto JSON en la capa de la aplicación, puede hacer el formateo / ordenar a medida que revisa los resultados.

NB No sabía que podía agregar DESC a una cláusula GROUP BY en MySQL, tal vez le falte una 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;
Arth
fuente
1
tenga en cuenta que la salida de EXTRACT(YEAR_MONTH FROM summaryDateTime)es201901
Edgar Ortega
@EdgarOrtega Sí, pero eso debería ser suficiente para generar el objeto JSON deseado en la pregunta original usando la lógica de la aplicación. Suponiendo que ya se está produciendo alguna forma de bucle sobre el resultado de la consulta, mi enfoque apunta a obtener la información mínima requerida de la base de datos de la manera más simple y rápida posible
Arth
1
Tienes razón, eso debería ser suficiente. Mi comentario fue solo para indicar cómo es la salida de esa función, tal vez a alguien no le guste ese formato.
Edgar Ortega
@EdgarOrtega ¡No te preocupes, gracias, un valioso aporte!
Arth
2

Debes hacer algo como esto

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
fuente
2

Tu también puedes hacer esto

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

a ordenar por año y mes. Supongamos que desea realizar un pedido desde este año y desde este mes hasta el mes 12

Niclausel
fuente
1

usar la función EXTRACCIÓN como esta

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

Así es como lo hago:

GROUP BY  EXTRACT(YEAR_MONTH FROM t.summaryDateTime);
CTBrewski
fuente
0

Está agrupando solo por mes, debe agregar AÑO () al grupo por

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

Aún así, necesitaría procesarlo en un script externo para obtener exactamente la estructura que está buscando.

Por ejemplo, use la explosión de PHP para crear una matriz a partir de la lista de nombres de meses y luego use json_encode ()

Mchl
fuente
-2

Utilizar

GROUP BY year, month DESC";

En vez de

GROUP BY MONTH(t.summaryDateTime) DESC";
Kyra
fuente
aunque parece que GROUP BY MONTH (t.summaryDateTime) DESC no ordena los meses correctamente por alguna razón ...
Derek Adair