SQL按客户分组提取前6个月工单统计数据的实现方案咨询
实现方案
不需要使用循环遍历,直接通过窗口函数ROW_NUMBER()按客户分组、按月份倒序排序后取前6条即可,适配你现有逻辑的优化语句如下:
WITH ClientMonthStats AS ( -- 封装你原有已验证可用的统计逻辑 SELECT Ticket_ClientName, COUNT(Ticket_ClientName) AS DisplayNameCount, CONCAT( DATEPART(YEAR, CAST(t.ticket_opendate AS DATE)), RIGHT('00'+ CONVERT(NVARCHAR(2),(DATEPART(MONTH, CAST(t.ticket_opendate AS DATE)))),2) ) AS OpenDate, DATENAME(MONTH, CAST(t.ticket_opendate AS DATE)) AS Month_Name FROM dbo.Ticket t WHERE t.Ticket_ClientName IS NOT NULL AND Ticket_DisplayId NOT LIKE 'EH%' AND Ticket_Statusname NOT LIKE 'Deleted' GROUP BY Ticket_ClientName, CONCAT(DATEPART(YEAR, CAST(t.ticket_opendate AS DATE)), RIGHT('00'+ CONVERT(NVARCHAR(2),(DATEPART(MONTH, CAST(t.ticket_opendate AS DATE)))),2)), DATENAME(MONTH, CAST(t.ticket_opendate AS DATE)) ), ClientMonthRank AS ( -- 按客户分组,每组内按月份倒序排序生成序号 SELECT *, ROW_NUMBER() OVER (PARTITION BY Ticket_ClientName ORDER BY OpenDate DESC) AS MonthRank FROM ClientMonthStats ) -- 取每个客户排序后的前6个月数据 SELECT Ticket_ClientName, DisplayNameCount, OpenDate, Month_Name FROM ClientMonthRank WHERE MonthRank <= 6 ORDER BY Ticket_ClientName, OpenDate DESC
逻辑说明
- 第一层CTE
ClientMonthStats直接复用你已有的统计逻辑,无需调整原有过滤规则 - 第二层CTE
ClientMonthRank中PARTITION BY Ticket_ClientName实现按客户分组,每组内按年月字段OpenDate倒序排序,最新的月份序号为1 - 最终外层查询仅保留序号≤6的记录,即可得到每个客户有数据的最近6个月工单统计
- 如果需要将无工单的月份统计值补0,可以先生成所有客户和近6个月的笛卡尔积,再左关联上述统计结果即可
补充说明
如果你需要的是全局统一的最近6个月数据(所有客户都统计同一个时间范围的工单),不需要窗口函数,直接在原有查询的WHERE子句中增加时间过滤条件即可,性能更优:
AND CAST(t.ticket_opendate AS DATE) >= DATEADD(MONTH, -6, GETDATE())
内容的提问来源于stack exchange,提问作者cai120
相关产品推荐
相关产品推荐

