Showing posts with label avg. Show all posts
Showing posts with label avg. Show all posts

Thursday, March 22, 2012

Adding to outputs together to retrieve the top(10) - Is it possible?

Hi There,

I have been struggling day and night with the creation of a store procedure due to not being able to retieve the rows I need for SUM and AVG functions.

I have two tables ('actions' & 'incident_types') which both have a score value for each record. In my database, I have reports that contain both action codes and incident_type codes based on a personnel_code.

In simple terms I'm trying to do the following:-

For all reports, find each personnel member and thier attached incident_types and action codes and then, for each score from the actions and incident_types tables, create the SUM of the 'combined' scores.

I have successfully retrieved the output for the scores individually but I need the TOP(10) of the combined output.....

I'm currently using to seperate queries as follows :--

--This gives me the incident type output...... Creating the 'Volume' column which is the total Score for incidetn_types

SELECT Top (@.Number) Personnel_details.personnel_code, Personnel_details.personnel_forename, Personnel_details.personnel_Surname, sum(incident_types.type_score) as 'Volume', avg(incident_types.type_score) as 'Average' INTO 'Incident_Scores' from Report_header

JOIN incident_types on incident_types.type_code = report_header.report_incident_Code

JOIN report_basedon on report_basedon.report_code = report_header.report_code

JOIN personnel_details on personnel_details.personnel_code = report_basedon.personnel_code

WHERE (report_header.report_date >= @.fromDate and report_header.report_date <= @.toDate)

AND (report_header.report_time >= @.fromTime and report_header.report_time <= @.toTime)

AND report_basedon.personnel_code <> 0

AND report_header.record_status=@.recordStatus

group by Personnel_details.personnel_code, Personnel_details.personnel_forename, Personnel_details.personnel_Surname

-- I then use the following to get the total of all action scores, again in the 'Volume' column

SELECT Top (@.Number) Personnel_details.personnel_code, Personnel_details.personnel_forename, Personnel_details.personnel_Surname, sum(actions.action_score) as 'Volume', AVG(actions.action_score) as 'Average' from profile

JOIN actions on actions.action_code = profile.action_code

JOIN report_header on report_header.report_code = profile.incident_ID

JOIN personnel_details on personnel_details.personnel_code = profile.personnel_code

WHERE (report_header.report_date >= @.fromDate and report_header.report_date <= @.toDate)

AND (report_header.report_time >= @.fromTime and report_header.report_time <= @.toTime)

AND personnel_details.personnel_code <> 0

AND report_header.record_status=@.recordStatus

AND profile.record_status=@.recordStatus

group by Personnel_details.personnel_code, Personnel_details.personnel_forename, Personnel_details.personnel_Surname

So my question is - How can I get the sum(incident_types.type_score) + sum(actions.action_score) and then get the TOP(10) rows?

Is it possible to output these 2 result to a new table and then join the new tables?

Thanks for any assistance, this is really draining me at the moment..... :-/

here it is,

Select TOP (@.Number)

incident_Data.personnel_code

, incident_Data.personnel_forename

, incident_Data.personnel_Surname

, incident_Data.Volume

, incident_Data.Average

, actions_data.Volume

, actions_data.Average

, incident_Data.Volume + actions_data.Volume as Total_Volume

, incident_Data.Average + actions_data.Average as Total_Average

from

(

SELECT

Personnel_details.personnel_code

, Personnel_details.personnel_forename

, Personnel_details.personnel_Surname

, sum(incident_types.type_score) as 'Volume'

, avg(incident_types.type_score) as 'Average'

from

Report_header

JOIN incident_types on incident_types.type_code = report_header.report_incident_Code

JOIN report_basedon on report_basedon.report_code = report_header.report_code

JOIN personnel_details on personnel_details.personnel_code = report_basedon.personnel_code

WHERE

(report_header.report_date >= @.fromDate and report_header.report_date <= @.toDate)

AND (report_header.report_time >= @.fromTime and report_header.report_time <= @.toTime)

AND report_basedon.personnel_code <> 0

AND report_header.record_status=@.recordStatus

group by

Personnel_details.personnel_code,

Personnel_details.personnel_forename,

Personnel_details.personnel_Surname

) as incident_Data

Inner Join

(

SELECT

Personnel_details.personnel_code

, Personnel_details.personnel_forename

, Personnel_details.personnel_Surname

, sum(actions.action_score) as 'Volume'

, AVG(actions.action_score) as 'Average'

from

profile

JOIN actions on actions.action_code = profile.action_code

JOIN report_header on report_header.report_code = profile.incident_ID

JOIN personnel_details on personnel_details.personnel_code = profile.personnel_code

WHERE

(report_header.report_date >= @.fromDate and report_header.report_date <= @.toDate)

AND (report_header.report_time >= @.fromTime and report_header.report_time <= @.toTime)

AND personnel_details.personnel_code <> 0

AND report_header.record_status=@.recordStatus

AND profile.record_status=@.recordStatus

group by

Personnel_details.personnel_code,

Personnel_details.personnel_forename,

Personnel_details.personnel_Surname

) as actions_data

On actions_data.personnel_code = incident_Data.personnel_code

|||

Thank you so much for your reply this has really made my day!

I forgot to mention that the action record is not always present but the incident record is. Therefore I made the actions_data join = 'Left Outer Join' (see code below)... This gives me a problem in that when the action_data record contains 'NULL' the Volume is also 'NULL' - is it possible to make NULL = 0 [zero] when there is no action record?

Thanks again (see code and output).....

[code I've removed some of the selection criteria from previous post for testing purposes]

Select TOP (1000)

incident_Data.personnel_code

, incident_Data.personnel_forename

, incident_Data.personnel_Surname

, incident_Data.Volume

, incident_Data.Average

, actions_data.Volume

, actions_data.Average

, incident_Data.Volume + actions_data.Volume as Total_Volume

, incident_Data.Average + actions_data.Average as Total_Average

from

(

SELECT

Personnel_details.personnel_code

, Personnel_details.personnel_forename

, Personnel_details.personnel_Surname

, sum(incident_types.type_score) as 'Volume'

, avg(incident_types.type_score) as 'Average'

from

Report_header

JOIN incident_types on incident_types.type_code = report_header.report_incident_Code

JOIN report_basedon on report_basedon.report_code = report_header.report_code

JOIN personnel_details on personnel_details.personnel_code = report_basedon.personnel_code

WHERE

report_basedon.personnel_code <> 0

AND report_header.record_status='1'

group by

Personnel_details.personnel_code,

Personnel_details.personnel_forename,

Personnel_details.personnel_Surname

) as incident_Data

Left Outer Join

(

SELECT

Personnel_details.personnel_code

, Personnel_details.personnel_forename

, Personnel_details.personnel_Surname

, sum(actions.action_score) as 'Volume'

, AVG(actions.action_score) as 'Average'

from

profile

JOIN actions on actions.action_code = profile.action_code

JOIN report_header on report_header.report_code = profile.incident_ID

JOIN personnel_details on personnel_details.personnel_code = profile.personnel_code

WHERE

personnel_details.personnel_code <> 0

AND report_header.record_status='1'

AND profile.record_status='1'

group by

Personnel_details.personnel_code,

Personnel_details.personnel_forename,

Personnel_details.personnel_Surname

) as actions_data

On actions_data.personnel_code = incident_Data.personnel_code

Order by incident_data.personnel_code

[example of results]

15 Oscar Freeman 0 0 NULL NULL NULL NULL
16 Sofia Daniels 0 0 NULL NULL NULL NULL
19 Megan Hardy 25 12 120 40 145 52
20 Finley Randall -25 -25 NULL NULL NULL NULL|||

observations

1. since actions_data subquery may be missing [i.e. OUTER JOIN] you should use this line instead

, incident_Data.Volume + ISNULL(actions_data.Volume,0) as Total_Volume

, incident_Data.Average + ISNULL(actions_data.Average,0) as Total_Average


2. the Total_Average calculation is flawed, e.g.
4 rows of incident_Data with average of 50 and 1 row of actions_data with average of 20 would yield a Total_Average of 70

when what you probably wanted was 44 (or 35 for simplicity if you don't care about weighting)

Dick

|||

Thank you Dick, for both points, your absolutly correct. I was so concerned with not being ale to extract the data that I hadn't thought this though. You've propably saved me a lot more pain!

Just for completeness, I had to go on and resolve a divide by zero error when calculating the final averages etc etc and I found a very useful link http://www.sql-server-helper.com/error-messages/msg-8134.aspx which shows 3 ways of dealing with this error.

Thanks again for everyones help - I can now get on with developing the program!!!!

|||

Yes. ISNULL will fix the issue... If the average is your issue the following query might be a best one..

Not sure why we need a TOP here.. It wont give any performance gain.

Select TOP (@.Number)

personnel_code

, personnel_forename

, personnel_Surname

, sum(case when type='incident' then Score end) as incident_volume

, avg(case when type='incident' then Score end) as incident_average

, sum(case when type='actions' then Score end) as actions_volume

, avg(case when type='actions' then Score end) as actions_average

, sum(Score) as Total_Volume

, avg(Score) as Total_Average

From

(

SELECT

Personnel_details.personnel_code

, Personnel_details.personnel_forename

, Personnel_details.personnel_Surname

, (incident_types.type_score) as 'Score'

, 'incident' Type

from

Report_header

JOIN incident_types on incident_types.type_code = report_header.report_incident_Code

JOIN report_basedon on report_basedon.report_code = report_header.report_code

JOIN personnel_details on personnel_details.personnel_code = report_basedon.personnel_code

WHERE

(report_header.report_date >= @.fromDate and report_header.report_date <= @.toDate)

AND (report_header.report_time >= @.fromTime and report_header.report_time <= @.toTime)

AND report_basedon.personnel_code <> 0

AND report_header.record_status=@.recordStatus

UNION ALL

SELECT

Personnel_details.personnel_code

, Personnel_details.personnel_forename

, Personnel_details.personnel_Surname

, (actions.action_score) as 'Score'

, 'actions' Type

from

profile

JOIN actions on actions.action_code = profile.action_code

JOIN report_header on report_header.report_code = profile.incident_ID

JOIN personnel_details on personnel_details.personnel_code = profile.personnel_code

WHERE

(report_header.report_date >= @.fromDate and report_header.report_date <= @.toDate)

AND (report_header.report_time >= @.fromTime and report_header.report_time <= @.toTime)

AND personnel_details.personnel_code <> 0

AND report_header.record_status=@.recordStatus

AND profile.record_status=@.recordStatus

) as data

Group By

personnel_code

, personnel_forename

, personnel_Surname

Monday, February 13, 2012

Adding Column AVGs on Matrix Reports

Hi,
Does anyone know how to add an AVG of a column in a matrix report? Its
obvious how to do a subtotal but I can't figure out how to add an
aggregate AVG for all columns. I also need to have the AVG below the
Column headers not at the bottom of the report as usual (see sample
below).
Column1 Column2 Column3
-- -- -- --
AVG 1.67 1.34 2
Row1 2 3 1
Row2 3 1 1
Row3 0 0 4
Any response is much appreciated.
Thanks,
ClaudeYou could write a simple expression like
=Sum(fields!Detail.Value)/Count(fields!Detail.Value) where detail is the
field pointing to 2,3...etc. instead of using subtotal. Insert a static row
at the top and use this expression. You could use tables instead of matrix (I
find it much cleaner than matrix specially when you dont have column
groupings and can do with row groupings)
"Claude" wrote:
> Hi,
> Does anyone know how to add an AVG of a column in a matrix report? Its
> obvious how to do a subtotal but I can't figure out how to add an
> aggregate AVG for all columns. I also need to have the AVG below the
> Column headers not at the bottom of the report as usual (see sample
> below).
> Column1 Column2 Column3
> -- -- -- --
> AVG 1.67 1.34 2
> Row1 2 3 1
> Row2 3 1 1
> Row3 0 0 4
> Any response is much appreciated.
> Thanks,
> Claude
>