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

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
fuente
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)
Bogdan Gavril MSFT
fuente
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
Andrei Sura
fuente
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
Aniket Warey
fuente
1

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

Jordán
fuente
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 -

John Sonnino
fuente
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;
Nida
fuente
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;
YHTAN
fuente
-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
user1845584
fuente
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;
Antonio raj
fuente