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.

Respuestas:


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

es lo que quieres.


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

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

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.


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;

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

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


1

usar la función EXTRACCIÓN como esta

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

1

Así es como lo hago:

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

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


-2

Utilizar

GROUP BY year, month DESC";

En vez de

GROUP BY MONTH(t.summaryDateTime) DESC";

aunque parece que GROUP BY MONTH (t.summaryDateTime) DESC no ordena los meses correctamente por alguna razón ...
Derek Adair
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.