Cómo agrupar por mes desde el campo Fecha usando SQL


84

¿Cómo puedo agrupar solo por mes desde un campo de fecha (y no agrupar por día)?

Así es como se ve mi campo de fecha:

2012-05-01

Aquí está mi SQL actual:

select  Closing_Date, Category,  COUNT(Status)TotalCount from  MyTable
where Closing_Date >= '2012-02-01' and Closing_Date <= '2012-12-31'
and Defect_Status1 is not null
group by  Closing_Date, Category

Respuestas:


108

Yo usaría esto:

SELECT  Closing_Date = DATEADD(MONTH, DATEDIFF(MONTH, 0, Closing_Date), 0), 
        Category,  
        COUNT(Status) TotalCount 
FROM    MyTable
WHERE   Closing_Date >= '2012-02-01' 
AND     Closing_Date <= '2012-12-31'
AND     Defect_Status1 IS NOT NULL
GROUP BY DATEADD(MONTH, DATEDIFF(MONTH, 0, Closing_Date), 0), Category;

Esto se agrupará el primero de cada mes, por lo que

`DATEADD(MONTH, DATEDIFF(MONTH, 0, '20130128'), 0)` 

dará '20130101'. Generalmente prefiero este método ya que mantiene las fechas como fechas.

Alternativamente, puede usar algo como esto:

SELECT  Closing_Year = DATEPART(YEAR, Closing_Date),
        Closing_Month = DATEPART(MONTH, Closing_Date),
        Category,  
        COUNT(Status) TotalCount 
FROM    MyTable
WHERE   Closing_Date >= '2012-02-01' 
AND     Closing_Date <= '2012-12-31'
AND     Defect_Status1 IS NOT NULL
GROUP BY DATEPART(YEAR, Closing_Date), DATEPART(MONTH, Closing_Date), Category;

Realmente depende de cuál sea el resultado deseado. (El año de cierre no es necesario en su ejemplo, pero si el rango de fechas cruza el límite de un año, puede serlo).


GarethD, gracias hombre, ambos métodos funcionaron bien. ¿Hay alguna forma de agrupar el año y el mes en un campo? Significado para mostrar este formato: dic-12 (dic es el mes y 12 es el año). gracias
user1858332

El primer método hará esto, solo necesita formatear la columna. Aconsejaría hacer esto fuera de SQL, pero si tiene que hacerse como tal, puede usar algo comoSELECT STUFF(SUBSTRING(CONVERT(VARCHAR, CURRENT_TIMESTAMP, 6), 4, 6), 4, 1, '-');
GarethD

@GarethD ¿Podrías explicar cómo usaste dateiff entre 0 y date? 0 no es una cita.
irfandar

1
y también ¿qué hace Closing_Date = DATEADD (MONTH, DATEDIFF (MONTH, 0, Closing_Date), 0) por qué no solo DATEADD (MONTH, DATEDIFF (MONTH, 0, Closing_Date), 0)
irfandar

3
@irfandar 0 no es una fecha, pero SQL-Server la convierte implícitamente al 1 de enero de 1900. Para su segunda pregunta Closing_Date =es solo el alias de la columna, es lo mismo que tener AS Closing_Datedespués de la expresión. Es completamente subjetivo pero personalmente encuentro la alias =notación mucho más fácil de leer que AS Alias. Para obtener más información sobre por qué lo prefiero, lea este artículo de Aaron Bertrand.
GarethD

41

Utilice la función DATEPART para extraer el mes de la fecha.

Entonces harías algo como esto:

SELECT DATEPART(month, Closing_Date) AS Closing_Month, COUNT(Status) AS TotalCount
FROM t
GROUP BY DATEPART(month, Closing_Date)

14
Para Mysql, puede usar MONTH () o MONTHNAME () en lugar de DATEPART
frazras

Si ejecuta esta consulta con frecuencia, considere la posibilidad de crear un índice adecuado.
user_0

Más 1 por respuesta simple.
berdem

9
Esto consideraría iguales meses de diferentes años, lo que normalmente NO se esperaba.
ivan_pozdeev

Esto pone un "1" para enero, etc. No le dice el nombre del mes
user890332

14

He utilizado el FORMATO función de lograr esto:

select
 FORMAT(Closing_Date, 'yyyy_MM') AS Closing_Month
 , count(*) cc 
FROM
 MyTable
WHERE
 Defect_Status1 IS NOT NULL
 AND Closing_Date >= '2011-12-01'
 AND Closing_Date < '2016-07-01' 
GROUP BY FORMAT(Closing_Date, 'yyyy_MM')
ORDER BY Closing_Month

9

Por adición MONTH(date_column)de GROUP BY.

SELECT Closing_Date, Category,  COUNT(Status)TotalCount
FROM   MyTable
WHERE  Closing_Date >= '2012-02-01' AND Closing_Date <= '2012-12-31'
AND    Defect_Status1 IS NOT NULL
GROUP BY MONTH(Closing_Date), Category

1

La función DATEPART no funciona en MySQL 5.6, en su lugar use MONTH ('2018-01-01')


1

Prueba esto:

select min(closing_date), date_part('month',closing_date) || '-' || date_part('year',closing_date) AS month,
Category, COUNT(Status)TotalCount 
FROM MyTable
where Closing_Date >= '2012-02-01' AND Closing_Date <= '2012-12-31'
AND Defect_Status1 is not null
GROUP BY month, Category,
ORDER BY 1

De esta manera, está agrupando por un formato de fecha concatenado, unido por un -


0
SELECT  to_char(Closing_Date,'MM'), 
        Category,  
        COUNT(Status) TotalCount 
FROM    MyTable
WHERE   Closing_Date >= '2012-02-01' 
AND     Closing_Date <= '2012-12-31'
AND     Defect_Status1 IS NOT NULL
GROUP BY Category;

0

Versión de SQL Server 2012 anterior,

SELECT  format(Closing_Date,'yyyy-MM') as ClosingMonth,
        Category,  
        COUNT(Status) TotalCount 
FROM    MyTable
WHERE   Closing_Date >= '2012-02-01' 
AND     Closing_Date <= '2012-12-31'
AND     Defect_Status1 IS NOT NULL
GROUP BY format(Closing_Date,'yyyy-MM'), Category;

-1

Puede hacer esto usando Year (), Month () Day () y datepart ().

En su ejemplo, esto sería:

select  Closing_Date, Category,  COUNT(Status)TotalCount from  MyTable
where Closing_Date >= '2012-02-01' and Closing_Date <= '2012-12-31' 
and Defect_Status1 is not null 
group by Year(Closing_Date), Month(Closing_Date), Category

Esto no es SQL válido
Mad Echet

Bueno, esto es válido pero trae resultados impredecibles ya que no agrupa por los campos que selecciona. Puede tener cualquier valor en la fecha de cierre siempre que la fecha y el año sean iguales.
Mad Echet

-1

Pruebe el siguiente código

SELECT  Closing_Date = DATEADD(MONTH, DATEDIFF(MONTH, 0, Closing_Date), 0), 
        Category,  
        COUNT(Status) TotalCount 
FROM    MyTable
WHERE   Closing_Date >= '2012-02-01' 
AND     Closing_Date <= '2012-12-31'
AND     Defect_Status1 IS NOT NULL
GROUP BY DATEADD(MONTH, DATEDIFF(MONTH, 0, Closing_Date), 0), Category;
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.