Solved

SQL query to summarize items per month

Posted on 2016-11-23
5
58 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
  • 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

3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Slow Connectivity over ODBC 8 32
T-SQL: Do I need CLUSTERED here? 13 39
Query Help - MSSQL - Averages 5 25
why sql server only update some statistics in the database ? 3 19
Slowly Changing Dimension Transformation component in data task flow is very useful for us to manage and control how data changes in SSIS.
Load balancing is the method of dividing the total amount of work performed by one computer between two or more computers. Its aim is to get more work done in the same amount of time, ensuring that all the users get served faster.
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.
Via a live example, show how to extract insert data into a SQL Server database table using the Import/Export option and Bulk Insert.

813 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

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now