?
Solved

SQL query to summarize items per month

Posted on 2016-11-23
5
Medium Priority
?
101 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 29

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 2000 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

Get 15 Days FREE Full-Featured Trial

Benefit from a mission critical IT monitoring with Monitis Premium or get it FREE for your entry level monitoring needs.
-Over 200,000 users
-More than 300,000 websites monitored
-Used in 197 countries
-Recommended by 98% of users

Question has a verified solution.

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

International Data Corporation (IDC) prognosticates that before the current the year gets over disbursing on IT framework products to be sent in cloud environs will be $37.1B.
Recently we ran in to an issue while running some SQL jobs where we were trying to process the cubes.  We got an error saying failure stating 'NT SERVICE\SQLSERVERAGENT does not have access to Analysis Services. So this is a way to automate that wit…
Viewers will learn how to use the SELECT statement in SQL and will be exposed to the many uses the SELECT statement has.
Viewers will learn how to use the UPDATE and DELETE statements to change or remove existing data from their tables. Make a table: Update a specific column given a specific row using the UPDATE statement: Remove a set of values using the DELETE s…
Suggested Courses

770 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