databarracks
asked on
SQL Query Group By with Days of the Current Week
Hi Guys,
I am trying to write a query in SQL 2005 that will be able to aggregate numbers from the current week day by day.I already use the below code to get working days with the current week:
This works fine. Now what I need to accomplish to to make a view that will extract all StartTime transactions within the results and count daily usage, grouped by user and each day of the current week appearing as a column.
I have attached a spreadsheet sample to show you the kind of thing I would like to achieve. Could someone please kindly assist me with transforming my data into my desired result as per attachment?
Many thanks for your help
I am trying to write a query in SQL 2005 that will be able to aggregate numbers from the current week day by day.I already use the below code to get working days with the current week:
(CONVERT(VARCHAR(8), view_calls_quality_1.StartTime, 112)
>= DATEADD(week, DATEDIFF(day, 0, GETDATE()) / 7, 0)) AND (CONVERT(VARCHAR(8), view_calls_quality_1.StartTime, 108) BETWEEN '07:00:00' AND
'19:00:00') AND (CONVERT(VARCHAR(8), view_calls_quality_1.StartTime, 112) <= DATEADD(week, DATEDIFF(day, 0, GETDATE()) / 7, 4))
This works fine. Now what I need to accomplish to to make a view that will extract all StartTime transactions within the results and count daily usage, grouped by user and each day of the current week appearing as a column.
I have attached a spreadsheet sample to show you the kind of thing I would like to achieve. Could someone please kindly assist me with transforming my data into my desired result as per attachment?
Many thanks for your help
Please rephrase your question. Post you entire SELECT statement, partial WHERE or JOIN conditions are not enough. And add your sheet.
ASKER
Ah just realised I didn't attach the spreadsheet, apologies for that. The spreadsheet does the explaining in itself.
Sample.xlsx
Sample.xlsx
ASKER
My Query
Which produces totals for each user in each day of the week.All that’s left is to create a view for which the days of the week are the columns and the name of the user. Please see attachment for concept again
SELECT dbo.view_users.user_full_name, COUNT(view_calls_quality.CallType) AS [Total], DATENAME(dw, view_calls_quality_1.StartTime) AS DayName
FROM dbo.view_users INNER JOIN
dbo.view_calls_quality AS view_calls_quality_1 ON
dbo.view_users.user_full_name = view_calls_quality_1.OriginationName
WHERE (view_calls_quality_1.CallType = 'Outbound') AND (view_calls_quality_1.Qualify = 'Qualified') AND (CONVERT(VARCHAR(8), view_calls_quality_1.StartTime, 112)
>= DATEADD(week, DATEDIFF(day, 0, GETDATE()) / 7, 0)) AND (CONVERT(VARCHAR(8), view_calls_quality_1.StartTime, 108) BETWEEN '07:00:00' AND
'19:00:00') AND (CONVERT(VARCHAR(8), view_calls_quality_1.StartTime, 112) <= DATEADD(week, DATEDIFF(day, 0, GETDATE()) / 7, 4))
GROUP BY dbo.view_users.user_full_name
Which produces totals for each user in each day of the week.All that’s left is to create a view for which the days of the week are the columns and the name of the user. Please see attachment for concept again
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
This is a great candidate for a PIVOT. You can use your query, as is. Try this query. If you like it, it should be no problem to turn it into a view.
;WITH myCTE (user_full_name, Total, DayName) AS (
SELECT dbo.view_users.user_full_name,
COUNT(view_calls_quality.CallType) AS [Total],
DATENAME(dw, view_calls_quality_1.StartTime) AS DayName
FROM dbo.view_users INNER JOIN
dbo.view_calls_quality AS view_calls_quality_1 ON
dbo.view_users.user_full_name = view_calls_quality_1.OriginationName
WHERE (view_calls_quality_1.CallType = 'Outbound') AND (view_calls_quality_1.Qualify = 'Qualified') AND (CONVERT(VARCHAR(8), view_calls_quality_1.StartTime, 112)
>= DATEADD(week, DATEDIFF(day, 0, GETDATE()) / 7, 0)) AND (CONVERT(VARCHAR(8), view_calls_quality_1.StartTime, 108) BETWEEN '07:00:00' AND
'19:00:00') AND (CONVERT(VARCHAR(8), view_calls_quality_1.StartTime, 112) <= DATEADD(week, DATEDIFF(day, 0, GETDATE()) / 7, 4))
GROUP BY dbo.view_users.user_full_name
)
SELECT user_full_name,
[MON],
[TUE],
[WED],
[THU],
[FRI]
FROM MyCTE
PIVOT ( SUM(Total) FOR DayName IN ([MON],[TUE],[WED],[THU],[FRI] ) ) pvt
ASKER
Hi Guys,
I like both of your queries would it be possible to pivot another field? What I mean is could I pivot the SUM(Total) and another one called SUM(Duration)?
I like both of your queries would it be possible to pivot another field? What I mean is could I pivot the SUM(Total) and another one called SUM(Duration)?
D'oh? But sounds like we need a CASE/GROUP BY pivot. Can you describe the input and output?
ASKER
OK so, your code is perfect but I have another field called duration which is an integer type that has the total seconds for a call. So I would like the same query you had but have two columns for the day of the week which shows the quantity and duration like the below table:
Name Monday MondayTime Tuesday TuesdayTime Wednesday WednesdayTime Thursday ThursdayTime Friday FridayTime
Person A 2 125 3 399 0 74 2 19 1 95
Person B 2 100 2 201 0 6 1 78 1 100
Person C 0 66 1 199 3 10 0 146 1 20
Also you can check this link out http://www.sqlsoldier.com/wp/sqlserver/smarpivottricks
Name Monday MondayTime Tuesday TuesdayTime Wednesday WednesdayTime Thursday ThursdayTime Friday FridayTime
Person A 2 125 3 399 0 74 2 19 1 95
Person B 2 100 2 201 0 6 1 78 1 100
Person C 0 66 1 199 3 10 0 146 1 20
Also you can check this link out http://www.sqlsoldier.com/wp/sqlserver/smarpivottricks
I used a field name called "Duration." Substitute that name for whatever truly is your field name. Try this:
;WITH myCTE AS (
SELECT dbo.view_users.user_full_name,
COUNT(view_calls_quality.CallType) AS [Total],
SUM(Duration) AS Duration,
DATENAME(dw, view_calls_quality_1.StartTime) AS DayName,
DATENAME(dw, view_calls_quality_1.StartTime) + 'Time' AS DayName2
FROM dbo.view_users INNER JOIN
dbo.view_calls_quality AS view_calls_quality_1 ON
dbo.view_users.user_full_name = view_calls_quality_1.OriginationName
WHERE (view_calls_quality_1.CallType = 'Outbound') AND (view_calls_quality_1.Qualify = 'Qualified') AND (CONVERT(VARCHAR(8), view_calls_quality_1.StartTime, 112)
>= DATEADD(week, DATEDIFF(day, 0, GETDATE()) / 7, 0)) AND (CONVERT(VARCHAR(8), view_calls_quality_1.StartTime, 108) BETWEEN '07:00:00' AND
'19:00:00') AND (CONVERT(VARCHAR(8), view_calls_quality_1.StartTime, 112) <= DATEADD(week, DATEDIFF(day, 0, GETDATE()) / 7, 4))
GROUP BY dbo.view_users.user_full_name
)
SELECT user_full_name,
[MON],
[TUE],
[WED],
[THU],
[FRI]
FROM MyCTE
PIVOT (SUM(Total) FOR DayName IN ([Monday],[Tuesday],[Wednesday],[Thursday],[Friday])) AS pvt1
PIVOT (SUM(Duration) FOR DayName2 IN ([MondayTime],[TuesdayTime],[WednesdayTime],[ThursdayTime],[FridayTime])) AS pvt2
ASKER
Hi dsacker,
I get "Invalid column name 'DayName2'." error?
I get "Invalid column name 'DayName2'." error?
Don't forget to add that in your SELECT statement. Note carefully how I added it in the SELECT in my example.
ASKER
Ok got it now
I'd opt instead for code below. I think it's easier to maintain. [Btw, I changed the StartTime comparisons to avoid using a function on the column except when absolutely necessary; otherwise, you could drastically reduce the usefulness of any index(es) on that column.]
SELECT vu.user_full_name,
SUM(CASE WHEN Day_Of_Week = 0 THEN 1 ELSE 0 END) AS Mon_Total,
SUM(CASE WHEN Day_Of_Week = 0 THEN DATEDIFF(MINUTE, vcq1.StartTime, vcq1.EndTime) ELSE 0 END) AS Mon_Duration,
SUM(CASE WHEN Day_Of_Week = 1 THEN 1 ELSE 0 END) AS Tue_Total,
SUM(CASE WHEN Day_Of_Week = 1 THEN DATEDIFF(MINUTE, vcq1.StartTime, vcq1.EndTime) ELSE 0 END) AS Tue_Duration,
SUM(CASE WHEN Day_Of_Week = 2 THEN 1 ELSE 0 END) AS Wed_Total,
SUM(CASE WHEN Day_Of_Week = 2 THEN DATEDIFF(MINUTE, vcq1.StartTime, vcq1.EndTime) ELSE 0 END) AS Wed_Duration,
SUM(CASE WHEN Day_Of_Week = 3 THEN 1 ELSE 0 END) AS Thu_Total,
SUM(CASE WHEN Day_Of_Week = 3 THEN DATEDIFF(MINUTE, vcq1.StartTime, vcq1.EndTime) ELSE 0 END) AS Thu_Duration,
SUM(CASE WHEN Day_Of_Week = 4 THEN 1 ELSE 0 END) AS Fri_Total,
SUM(CASE WHEN Day_Of_Week = 4 THEN DATEDIFF(MINUTE, vcq1.StartTime, vcq1.EndTime) ELSE 0 END) AS Fri_Duration
FROM dbo.view_users vu INNER JOIN
dbo.view_calls_quality AS vcq1 ON
vu.user_full_name = vcq1.OriginationName
--assign alias name to day calc to avoid repeating it throughout the SELECT and make code easier to follow
CROSS APPLY (
SELECT DATEDIFF(DAY, 0, vcq1.StartTime) % 7 AS Day_Of_Week --0=Mon;1=Tue;...;4=Fri.
) AS ca1
WHERE (vcq1.CallType = 'Outbound') AND
(vcq1.Qualify = 'Qualified') AND
(vcq1.StartTime >= DATEADD(HOUR, 7, DATEADD(WEEK, DATEDIFF(DAY, 0, GETDATE()) / 7, 0))) AND
(vcq1.StartTime < DATEADD(HOUR, 19, DATEADD(WEEK, DATEDIFF(DAY, 0, GETDATE()) / 7, 5))) AND
(DATEPART(HOUR, vcq1.StartTime) <= 18)
GROUP BY vu.user_full_name
--ORDER BY vu.user_full_name
SELECT vu.user_full_name,
SUM(CASE WHEN Day_Of_Week = 0 THEN 1 ELSE 0 END) AS Mon_Total,
SUM(CASE WHEN Day_Of_Week = 0 THEN DATEDIFF(MINUTE, vcq1.StartTime, vcq1.EndTime) ELSE 0 END) AS Mon_Duration,
SUM(CASE WHEN Day_Of_Week = 1 THEN 1 ELSE 0 END) AS Tue_Total,
SUM(CASE WHEN Day_Of_Week = 1 THEN DATEDIFF(MINUTE, vcq1.StartTime, vcq1.EndTime) ELSE 0 END) AS Tue_Duration,
SUM(CASE WHEN Day_Of_Week = 2 THEN 1 ELSE 0 END) AS Wed_Total,
SUM(CASE WHEN Day_Of_Week = 2 THEN DATEDIFF(MINUTE, vcq1.StartTime, vcq1.EndTime) ELSE 0 END) AS Wed_Duration,
SUM(CASE WHEN Day_Of_Week = 3 THEN 1 ELSE 0 END) AS Thu_Total,
SUM(CASE WHEN Day_Of_Week = 3 THEN DATEDIFF(MINUTE, vcq1.StartTime, vcq1.EndTime) ELSE 0 END) AS Thu_Duration,
SUM(CASE WHEN Day_Of_Week = 4 THEN 1 ELSE 0 END) AS Fri_Total,
SUM(CASE WHEN Day_Of_Week = 4 THEN DATEDIFF(MINUTE, vcq1.StartTime, vcq1.EndTime) ELSE 0 END) AS Fri_Duration
FROM dbo.view_users vu INNER JOIN
dbo.view_calls_quality AS vcq1 ON
vu.user_full_name = vcq1.OriginationName
--assign alias name to day calc to avoid repeating it throughout the SELECT and make code easier to follow
CROSS APPLY (
SELECT DATEDIFF(DAY, 0, vcq1.StartTime) % 7 AS Day_Of_Week --0=Mon;1=Tue;...;4=Fri.
) AS ca1
WHERE (vcq1.CallType = 'Outbound') AND
(vcq1.Qualify = 'Qualified') AND
(vcq1.StartTime >= DATEADD(HOUR, 7, DATEADD(WEEK, DATEDIFF(DAY, 0, GETDATE()) / 7, 0))) AND
(vcq1.StartTime < DATEADD(HOUR, 19, DATEADD(WEEK, DATEDIFF(DAY, 0, GETDATE()) / 7, 5))) AND
(DATEPART(HOUR, vcq1.StartTime) <= 18)
GROUP BY vu.user_full_name
--ORDER BY vu.user_full_name
ASKER
Very good job and thanks to the experts