如何使用sql从日期字段按月分组

Posted

技术标签:

【中文标题】如何使用sql从日期字段按月分组【英文标题】:How to group by month from Date field using sql 【发布时间】:2013-01-28 15:50:27 【问题描述】:

如何从日期字段中仅按月分组(而不是按天分组)?

这是我的日期字段的样子:

2012-05-01

这是我当前的 SQL:

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

【问题讨论】:

【参考方案1】:

我会用这个:

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;

这将按每个月的第一天分组,所以

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

会给'20130101'。我通常更喜欢这种方法,因为它将日期保留为日期。

或者你可以使用这样的东西:

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;

这真的取决于你想要的输出是什么。 (在您的示例中,结束年份不是必需的,但如果日期范围跨越年份边界,则可能是)。

【讨论】:

GarethD,谢谢伙计,这两种方法都很好用。有没有办法可以将年份和月份组合在一个字段中?意思是像这种格式显示:Dec-12(Dec 是月份,12 是年份)。谢谢 第一种方法会这样做,您只需要格式化列。我建议在 SQL 之外执行此操作,但如果必须这样做,您可以使用类似SELECT STUFF(SUBSTRING(CONVERT(VARCHAR, CURRENT_TIMESTAMP, 6), 4, 6), 4, 1, '-'); @GarethD 你能解释一下你是如何在 0 和日期之间使用 datediff 的吗? 0 不是日期。 还有什么 Closing_Date = DATEADD(MONTH, DATEDIFF(MONTH, 0, Closing_Date), 0) 为什么不只是 DATEADD(MONTH, DATEDIFF(MONTH, 0, Closing_Date), 0) 跨度> @irfandar 0 不是日期,但 SQL-Server 将其隐式转换为 1900 年 1 月 1 日。对于您的第二个问题,Closing_Date = 只是列别名,它与 AS Closing_Date 相同在表达式之后。这完全是主观的,但我个人发现alias = 符号比AS Alias 更容易阅读。有关我为什么更喜欢它的更多信息 read this article Aaron Bertrand。【参考方案2】:

使用DATEPART 函数从日期中提取月份。

所以你会做这样的事情:

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

【讨论】:

mysql 可以使用 MONTH() 或 MONTHNAME() 代替 DATEPART 如果您经常运行此查询,请考虑构建适当的索引。 简单回复加1。 这会将不同年份的月份视为相同 - 这通常不是预期的。 这会为一月等添加一个“1”。它不会告诉你月份名称【参考方案3】:

我使用FORMAT 函数来完成此操作:

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

【讨论】:

这不起作用,因为您不能在 ORDER BY 子句中使用别名【参考方案4】:

通过在GROUP BY 中添加MONTH(date_column)

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

【讨论】:

【参考方案5】:

试试这个:

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

这样你就可以通过连接的日期格式进行分组,并用 - 连接

【讨论】:

【参考方案6】:

DATEPART 函数在 MySQL 5.6 上不起作用,而是使用 MONTH('2018-01-01')

【讨论】:

【参考方案7】:
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;

【讨论】:

【参考方案8】:

SQL Server 2012 以上版本,

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;

【讨论】:

【参考方案9】:

您可以使用 Year()、Month() Day() 和 datepart() 来做到这一点。

在你的例子中,这将是:

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

【讨论】:

这不是有效的 SQL 嗯,这是有效的,但会带来不可预知的结果,因为您没有按您选择的字段进行分组。只要日期和年份相同,您可以在截止日期中设置任何值。【参考方案10】:

试试下面的代码

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;

【讨论】:

以上是关于如何使用sql从日期字段按月分组的主要内容,如果未能解决你的问题,请参考以下文章

SQL 查询:计数,按月-年分组,具有多个日期字段

sql中如何把具体日期转化为按月排序?

SQL按月统计,按日分组

LINQ:在日期时间字段中按月和年分组

如何在 Jooq 中按月和年将毫秒翻译成日期和分组?

mysql 如何按月分组查询出当前年度每个月的短信数量(数据库中这个月要是为空的话就用0条怎么显示出来)