Reputation: 165
I have a dataset that looks like this:
GO
CREATE TABLE [dbo].[taskDB](
[ticket] [varchar](50) NULL,
[created] [date] NULL,
[closed] [date] NULL,
[rating] [varchar](50) NULL
[user] [varchar](50) NULL
) ON [PRIMARY]
GO
INSERT [dbo].[taskDB] ([ticket], [created], [closed], [rating], [user]) VALUES (N'023345', CAST(N'2019-09-01' AS Date), CAST(N'2020-01-17' AS Date), N'Low', N'John')
GO
INSERT [dbo].[taskDB] ([ticket], [created], [closed], [rating], [user]) VALUES (N'023346', CAST(N'2019-08-01' AS Date), CAST(N'2019-08-03' AS Date), N'Critical', N'Tom')
GO
INSERT [dbo].[taskDB] ([ticket], [created], [closed], [rating], [user]) VALUES (N'023347', CAST(N'2019-09-01' AS Date), CAST(N'2019-09-20' AS Date), N'Critical', N'Pete')
GO
INSERT [dbo].[taskDB] ([ticket], [created], [closed], [rating], [user]) VALUES (N'023348', CAST(N'2019-08-01' AS Date), CAST(N'2020-08-06' AS Date), N'Critical', N'John')
GO
INSERT [dbo].[taskDB] ([ticket], [created], [closed], [rating], [user]) VALUES (N'023349', CAST(N'2020-08-01' AS Date), CAST(N'2020-08-05' AS Date), N'Medium', N'Tom')
GO
INSERT [dbo].[taskDB] ([ticket], [created], [closed], [rating], [user]) VALUES (N'023350', CAST(N'2019-08-01' AS Date), CAST(N'2019-08-05' AS Date), N'Medium', N'Pete')
GO
INSERT [dbo].[taskDB] ([ticket], [created], [closed], [rating], [user]) VALUES (N'023351', CAST(N'2019-12-22' AS Date), CAST(N'' AS Date), N'High', N'Tom')
GO
INSERT [dbo].[taskDB] ([ticket], [created], [closed], [rating], [user]) VALUES (N'023352', CAST(N'2019-11-07' AS Date), CAST(N'2020-08-05' AS Date), N'Medium', N'John')
GO
INSERT [dbo].[taskDB] ([ticket], [created], [closed], [rating], [user]) VALUES (N'023353', CAST(N'2020-08-02' AS Date), CAST(N'' AS Date), N'Low', N'Pete')
GO
INSERT [dbo].[taskDB] ([ticket], [created], [closed], [rating], [user]) VALUES (N'023354', CAST(N'2019-08-02' AS Date), CAST(N'2019-08-05' AS Date), N'Medium'N, 'Tom')
GO
INSERT [dbo].[taskDB] ([ticket], [created], [closed], [rating], [user]) VALUES (N'023355', CAST(N'2019-010-02' AS Date), CAST(N'' AS Date), N'Low', N'John')
GO
INSERT [dbo].[taskDB] ([ticket], [created], [closed], [rating], [user]) VALUES (N'023356', CAST(N'2019-08-02' AS Date), CAST(N'2019-08-05' AS Date), N'Critical', N'John')
GO
INSERT [dbo].[taskDB] ([ticket], [created], [closed], [rating], [user]) VALUES (N'023357', CAST(N'2019-08-06' AS Date), CAST(N'2020-07-05' AS Date), N'Critical', N'Tom')
GO
INSERT [dbo].[taskDB] ([ticket], [created], [closed], [rating], [user]) VALUES (N'023358', CAST(N'2019-10-04' AS Date), CAST(N'' AS Date), N'Low', N'John')
GO
INSERT [dbo].[taskDB] ([ticket], [created], [closed], [rating], [user]) VALUES (N'023359', CAST(N'2019-12-02' AS Date), CAST(N'2020-02-25' AS Date), N'High', N'Pete')
GO
INSERT [dbo].[taskDB] ([ticket], [created], [closed], [rating], [user]) VALUES (N'023360', CAST(N'2019-08-05' AS Date), CAST(N'2019-08-05' AS Date), N'Medium', N'John')
GO
INSERT [dbo].[taskDB] ([ticket], [created], [closed], [rating], [user]) VALUES (N'023361', CAST(N'2020-08-02' AS Date), CAST(N'' AS Date), N'High', N'John')
GO
INSERT [dbo].[taskDB] ([ticket], [created], [closed], [rating], [user]) VALUES (N'023362', CAST(N'2019-09-02' AS Date), CAST(N'2019-10-06' AS Date), N'Critical', N'Pete')
GO
INSERT [dbo].[taskDB] ([ticket], [created], [closed], [rating], [user]) VALUES (N'023363', CAST(N'2019-10-03' AS Date), CAST(N'2019-11-08' AS Date), N'High', N'Pete')
GO
INSERT [dbo].[taskDB] ([ticket], [created], [closed], [rating], [user]) VALUES (N'023365', CAST(N'2019-10-03' AS Date), CAST(N'2019-12-08' AS Date), N'N/A', N'Pete')
GO
INSERT [dbo].[taskDB] ([ticket], [created], [closed], [rating], [user]) VALUES (N'023364', CAST(N'2019-11-03' AS Date), CAST(N'2019-11-05' AS Date), N'High', N'John')
GO
INSERT [dbo].[taskDB] ([ticket], [created], [closed], [rating], [user]) VALUES (N'023366', CAST(N'2020-06-03' AS Date), CAST(N'' AS Date), N'High', N'John')
GO
INSERT [dbo].[taskDB] ([ticket], [created], [closed], [rating], [user]) VALUES (N'023368', CAST(N'2019-08-03' AS Date), CAST(N'2019-08-05' AS Date), N'High', N'John')
GO
INSERT [dbo].[taskDB] ([ticket], [created], [closed], [rating], [user]) VALUES (N'023367', CAST(N'2019-11-03' AS Date), CAST(N'' AS Date), N'N/A', N'Pete')
GO
INSERT [dbo].[taskDB] ([ticket], [created], [closed], [rating], [user]) VALUES (N'023371', CAST(N'2019-08-03' AS Date), CAST(N'2019-08-05' AS Date), N'N/A', N'John')
GO
INSERT [dbo].[taskDB] ([ticket], [created], [closed], [rating], [user]) VALUES (N'023370', CAST(N'2019-08-03' AS Date), CAST(N'2019-08-05' AS Date), N'Critical', N'Pete')
GO
I am using the following query to count the number of tickets closed per month:
declare @FromDate datetime,
@ToDate datetime;
SET @FromDate = (Select min(created) From [dbo].[taskDB]);
SET @ToDate = (Select max(created) From [dbo].[taskDB]);
declare @openTicketsByMonth table (firstDayOfMonth datetime, firstDayNextMonth datetime, year int, month int, count int)
Insert into @openTicketsByMonth(firstDayOfMonth, firstDayNextMonth, year, month)
Select top (datediff(month, @FromDate, @ToDate) + 1)
dateadd(month, number, @FromDate),
dateadd(month, number + 1, @FromDate),
year(dateadd(month, number, @FromDate)),
month(dateadd(month, number, @FromDate))
from [master].dbo.spt_values
where [type] = N'P' order by number;
update R
Set R.count = (Select count(1) from [dbo].[taskDB] where created < R.firstDayNextMonth and (closed <= R.firstDayNextMonth and closed >= R.firstDayOfMonth)),
From @openTicketsByMonth R
select year,
month,
count
from @openTicketsByMonth
I want to show the amount of tickets closed per month BY each user but I cannot get the INSERT INTO-Select statement include a set of rows for each users that outline the count by month. I am guessing i would need some sort of while loop that iterates over a temporary table that includes a list of distinct users to accomplish this. I know loops in MSSQL are not the best to implement. What is the best way to accomplish this?
Upvotes: 1
Views: 243
Reputation: 2100
You don't need a loop, derive year and month and then group by them
;WITH cteMonth as (
SELECT ticket,created,closed,rating,[user] as UserName
, YEAR(closed) as ClosedYear
, MONTH(closed) as ClosedMonth
FROM dbo.taskDB
)SELECT COUNT(ticket) as ClosedCount, UserName, ClosedYear, ClosedMonth
FROM cteMonth
GROUP BY ClosedYear, ClosedMonth, UserName
ORDER BY ClosedYear, ClosedMonth, UserName
Also, I don't think you need them for this, but in case I misunderstood your question and you want start and end dates in this you can back-derive them from year and month as follows
, DATEFROMPARTS (ClosedYear, ClosedMonth, 1) as firstDayOfMonth , DATEADD(month, 1, DATEFROMPARTS (ClosedYear, ClosedMonth, 1)) as firstDayNextMonth
And one more thought, you don't need to put the results into a temporary table, but if you wanted to the syntax would be as follows
declare @ClosedTicketsByUser table (Username nvarchar(50), firstDayOfMonth datetime, firstDayNextMonth datetime, ClosedYear int, ClosedMonth int, ClosedCount int)
;WITH cteMonth as (
SELECT ticket,created,closed,rating,[user] as UserName
, YEAR(closed) as ClosedYear
, MONTH(closed) as ClosedMonth
FROM dbo.taskDB
)
INSERT INTO @ClosedTicketsByUser(ClosedCount, UserName, ClosedYear, ClosedMonth, firstDayOfMonth, firstDayNextMonth)
SELECT COUNT(ticket) as ClosedCount, UserName, ClosedYear, ClosedMonth
, DATEFROMPARTS (ClosedYear, ClosedMonth, 1) as firstDayOfMonth
, DATEADD(month, 1, DATEFROMPARTS (ClosedYear, ClosedMonth, 1)) as firstDayNextMonth
FROM cteMonth
GROUP BY ClosedYear, ClosedMonth, UserName
ORDER BY ClosedYear, ClosedMonth, UserName
SELECT * FROM @ClosedTicketsByUser
EDIT: In the comment you said you wanted zeros added back in so you can plot this, you can still do that with this structure by adding in a temporary table of USERS x DATES and COALESCE in the zeros over NULLS
;WITH cteTickets as (
SELECT ticket,created,closed,rating,[user] as UserName
, YEAR(closed) as ClosedYear
, MONTH(closed) as ClosedMonth
FROM dbo.taskDB
), cteUsers as (SELECT DISTINCT UserName FROM cteTickets
), cteDates as (SELECT DISTINCT ClosedYear, ClosedMonth
, DATEFROMPARTS (ClosedYear, ClosedMonth, 1) as firstDayOfMonth
, DATEADD(month, 1, DATEFROMPARTS (ClosedYear, ClosedMonth, 1)) as firstDayNextMonth
FROM cteTickets
), cteCount as (SELECT COUNT(ticket) as ClosedCount, UserName, ClosedYear, ClosedMonth
FROM cteTickets GROUP BY ClosedYear, ClosedMonth, UserName
) SELECT U.*, D.*, COALESCE(C.ClosedCount, 0) as ClosedCount
FROM cteUsers as U CROSS JOIN cteDates as D
LEFT OUTER JOIN cteCount as C ON C.UserName = U.UserName AND C.ClosedYear = D.ClosedYear AND C.ClosedMonth = D.ClosedMonth
ORDER BY firstDayOfMonth, UserName
EDIT: Here it is with a pivot table as requested in comments
;WITH cteTickets as (
SELECT ticket,created,closed,rating,[user] as UserName
, YEAR(closed) as ClosedYear
, MONTH(closed) as ClosedMonth
FROM dbo.taskDB
), cteUsers as (SELECT DISTINCT UserName FROM cteTickets
), cteDates as (SELECT DISTINCT ClosedYear, ClosedMonth
, DATEFROMPARTS (ClosedYear, ClosedMonth, 1) as firstDayOfMonth
, DATEADD(month, 1, DATEFROMPARTS (ClosedYear, ClosedMonth, 1)) as firstDayNextMonth
FROM cteTickets
), cteCount as (SELECT COUNT(ticket) as ClosedCount, UserName, ClosedYear, ClosedMonth
FROM cteTickets GROUP BY ClosedYear, ClosedMonth, UserName
), cteFinal as ( SELECT U.*, D.*, COALESCE(C.ClosedCount, 0) as ClosedCount
FROM cteUsers as U CROSS JOIN cteDates as D
LEFT OUTER JOIN cteCount as C ON C.UserName = U.UserName AND C.ClosedYear = D.ClosedYear AND C.ClosedMonth = D.ClosedMonth
)
SELECT firstDayOfMonth, [John], [Pete], [Tom] FROM (SELECT * FROM cteFinal) as F
PIVOT (MIN(ClosedCount) FOR UserName IN ([John], [Pete], [Tom])) as P
ORDER BY firstDayOfMonth
Upvotes: 1