Solved

SQL query to summarize items per month

Posted on 2016-11-23
5
78 Views
Last Modified: 2016-12-28
We have a current SQL query which summarizes the hours worked by a particular branches staff.  Rather then running this report every month I would like to create a new report which automatically calculates the totals for each month, over an 18 month period.

EXAMPLE:

Current query has TOTAL HOURS -- EMPLOYEE FIRST NAME -- EMPLOYEE LAST NAME as headers.

I would like to see: EMPLOYEE FIRST - EMPLOYEE LAST - 2015JAN - 2015FEB...2016JAN - 2016FEB...

The current query is listed below:

use DB1
go
select      sum(timesheet_orders.no_of_hours) as TotalHours,
            user_profile.first_name, user_profile.last_name
From orders
            Inner Join timesheet_orders on orders.order_id = timesheet_orders.order_id
            Inner Join timesheet_header on timesheet_orders.timesheet_number = timesheet_header.timesheet_number
            Inner Join client_organization on orders.group_id = client_organization.group_id
            Inner Join user_profile on timesheet_header.contractor_id = user_profile.user_id

where timesheet_header.start_date >= dateadd(mm,-1,getdate())
             and timesheet_orders.status = 'P' and orders.office_id = '2601'

group by user_profile.first_name, user_profile.last_name

order by TotalHours desc


I know another query we created uses the DATEPART command but I am unsure of the proper syntax to use something like this with our current query.

Any assistance would be appreciated.
0
Comment
Question by:DrakeCA
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
  • 2
5 Comments
 
LVL 28

Expert Comment

by:Pawan Kumar
ID: 41899988
* - Added MS SQL Servers as Topic.

try..
use DB1
go
select      sum(timesheet_orders.no_of_hours) as TotalHours, 
            user_profile.first_name, user_profile.last_name,
			YEAR(timesheet_header.start_date) + ' ' + LEFT(DATENAME(MONTH,timesheet_header.start_date),3) YearMonth 
From orders
            Inner Join timesheet_orders on orders.order_id = timesheet_orders.order_id
            Inner Join timesheet_header on timesheet_orders.timesheet_number = timesheet_header.timesheet_number
            Inner Join client_organization on orders.group_id = client_organization.group_id
            Inner Join user_profile on timesheet_header.contractor_id = user_profile.user_id

where timesheet_header.start_date >= dateadd(mm,-1,getdate()) 
      and timesheet_orders.status = 'P' and orders.office_id = '2601'

group by user_profile.first_name, user_profile.last_name, YEAR(timesheet_header.start_date), MONTH(timesheet_header.start_date)

order by TotalHours desc

Open in new window

0
 

Author Comment

by:DrakeCA
ID: 41900572
Thanks for the input.  Looks interesting.

When I try running it I get the following error:

"Msg 8120, Level 16, State 1, Line 1
Column 'timesheet_header.start_date' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause."


Any suggestions?
0
 
LVL 69

Accepted Solution

by:
Scott Pletcher earned 500 total points
ID: 41901748
The easiest way to get the specific "yyyyMth" column names you want is to create the table with generic column names and rename them to specific names after loading the table.  Here's code to do all that; be sure to finish the code for all 18 months first before running.

if object_id('tempdb.dbo.#TotalHours') is not null
    drop table #TotalHours

--use generic column names for monthly totals, will be renamed later to exact yyyyMth name.    
select      
            user_profile.first_name, user_profile.last_name,
            sum(case when timesheet_header.start_date >= dateadd(month, datediff(month, 0, getdate()) - 18, 0) and
                          timesheet_header.start_date < dateadd(month, datediff(month, 0, getdate()) - 17, 0)
                     then timesheet_orders.no_of_hours else 0 end) as TotalHours_18MonthsAgo,
            sum(case when timesheet_header.start_date >= dateadd(month, datediff(month, 0, getdate()) - 17, 0) and
                          timesheet_header.start_date < dateadd(month, datediff(month, 0, getdate()) - 16, 0)
                     then timesheet_orders.no_of_hours else 0 end) as TotalHours_17MonthsAgo,
            sum(case when timesheet_header.start_date >= dateadd(month, datediff(month, 0, getdate()) - 16, 0) and
                          timesheet_header.start_date < dateadd(month, datediff(month, 0, getdate()) - 15, 0)
                     then timesheet_orders.no_of_hours else 0 end) as TotalHours_16MonthsAgo,
            sum(case when timesheet_header.start_date >= dateadd(month, datediff(month, 0, getdate()) - 15, 0) and
                          timesheet_header.start_date < dateadd(month, datediff(month, 0, getdate()) - 14, 0)
                     then timesheet_orders.no_of_hours else 0 end) as TotalHours_15MonthsAgo,
            sum(case when timesheet_header.start_date >= dateadd(month, datediff(month, 0, getdate()) - 14, 0) and
                          timesheet_header.start_date < dateadd(month, datediff(month, 0, getdate()) - 13, 0)
                     then timesheet_orders.no_of_hours else 0 end) as TotalHours_14MonthsAgo,
            --,...fill in the code for 13Months thru 02Months,using the code pattern shown...
            sum(case when timesheet_header.start_date >= dateadd(month, datediff(month, 0, getdate()) - 01, 0) and
                          timesheet_header.start_date < dateadd(month, datediff(month, 0, getdate()) - 00, 0)
                     then timesheet_orders.no_of_hours else 0 end) as TotalHours_01MonthsAgo,
            sum(timesheet_orders.no_of_hours) as TotalHours_AllMonths

Into #TotalHours
From orders
            Inner Join timesheet_orders on orders.order_id = timesheet_orders.order_id
            Inner Join timesheet_header on timesheet_orders.timesheet_number = timesheet_header.timesheet_number
            Inner Join client_organization on orders.group_id = client_organization.group_id
            Inner Join user_profile on timesheet_header.contractor_id = user_profile.user_id

where timesheet_header.start_date >= dateadd(month, datediff(month, 0, getdate()) - 18, 0)
             and timesheet_orders.status = 'P' and orders.office_id = '2601'

group by user_profile.first_name, user_profile.last_name

order by TotalHours_AllMonths desc


--rename generic column names to exact yyyyMth name.    
declare @column_name_original varchar(100)
declare @column_name_original_month_offset int
declare @column_name_yyyyMth varchar(7)
declare @month_number int
declare @timesheet_month date

set @column_name_original = 'dbo.#TotalHours.TotalHours_18MonthsAgo'
set @column_name_original_month_offset = PATINDEX('%[0-9]%', @column_name_original)
set @month_number = 18
while @month_number > 0
begin
    set @timesheet_month = dateadd(month, datediff(month, 0, getdate()) - @month_number, 0)
    set @column_name_original = stuff(@column_name_original, @column_name_original_month_offset,
        2, right('0' + cast(@month_number as varchar(2)), 2))
    set @column_name_yyyyMth = cast(year(@timesheet_month) as varchar(4)) + left(datename(month, @timesheet_month), 3)
    exec tempdb.sys.sp_rename @column_name_original, @column_name_yyyyMth, 'COLUMN'
    set @month_number = @month_number - 1    
end /*while*/


select *
from #TotalHours
order by TotalHours_AllMonths desc, last_name, first_name
0
 

Author Closing Comment

by:DrakeCA
ID: 41901914
This does exactly what I need it to.  Thanks so much for your assistance!
0
 
LVL 69

Expert Comment

by:Scott Pletcher
ID: 41901916
You're welcome!  The totalling technique is very helpful once you see it used and get used to it.  Btw, the column renaming code actually took more time than the totals query itself :-) .
0

Featured Post

Best Practices: Disaster Recovery Testing

Besides backup, any IT division should have a disaster recovery plan. You will find a few tips below relating to the development of such a plan and to what issues one should pay special attention in the course of backup planning.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

In this article I will describe the Detach & Attach method as one possible migration process and I will add the extra tasks needed for an upgrade when and where is applied so it will cover all.
Slowly Changing Dimension Transformation component in data task flow is very useful for us to manage and control how data changes in SSIS.
This video shows how to set up a shell script to accept a positional parameter when called, pass that to a SQL script, accept the output from the statement back and then manipulate it in the Shell.
Via a live example combined with referencing Books Online, show some of the information that can be extracted from the Catalog Views in SQL Server.

730 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question