Solved

# How to optimize this procedure.

Posted on 2013-06-14
139 Views
select Course,Subjectcode,
round(avg(cast(total as decimal(18,5))),2) as 'Avg',
round(stdev(cast(total as decimal(18,5))),2) as 'SD',
round(avg(cast(total as decimal(18,5)))+1.645*stdev(cast(total as decimal(18,5))),2) as 'xbarplus1645sd',
round(avg(cast(total as decimal(18,5)))+stdev(cast(total as decimal(18,5))),2) as 'xbarplussd',
round(avg(cast(total as decimal(18,5)))+.5*stdev(cast(total as decimal(18,5))),2) as 'xbarplus5sd',
round(avg(cast(total as decimal(18,5))),2) as 'xbar',
round(avg(cast(total as decimal(18,5)))-.5*stdev(cast(total as decimal(18,5))),2) as 'xbarminus5sd',
round(avg(cast(total as decimal(18,5)))-stdev(cast(total as decimal(18,5))),2) as 'xbarminussd',
round(avg(cast(total as decimal(18,5)))-1.645*stdev(cast(total as decimal(18,5))),2) as 'xbarminus1645sd'
from mstmassstudents
where ems not in('F','E','I','UMC','SS','',' ')
and  ims not in('F','E','I','UMC','SS','',' ')
group by course,subjectcode
order by 1,2,3

Procedure - why taking time.
I have course, subjectcode, total based on whcih the grades are calculated for each uid,
The code is attached herewith sample data/
Procedure-Attached.txt
smap.xlsx
0
Question by:searchsanjaysharma
• 5
• 4
• 2

LVL 48

Expert Comment

why do you use a cursor based stored procedure for this and not an update statement?

one thing that strikes me you do a lot of casting within the calculations - perhaps cast total to decimal through a nested subquery - that might save some cycles.
0

Author Comment

Nesting has to be done, as we need to calculate avg ans stdev per subject code and based on that the formula is applied to generate the grades.
0

LVL 48

Expert Comment

>>calculate avg and stdev per subject code
ok, this has to be done

use of cursor approach however remains a choice

any chance of getting some sample data from [gradestatistics]?
0

LVL 4

Assisted Solution

BAKADY earned 167 total points
you can replace you code between beginn and end with this:
``````with cte_mstmassstudents as (
select uid,
course,
subjectcode,
cast(total as bigint) as total
from mstmassstudents
where ems not in('F','E','I','UMC','SS','',' ')
and  ims not in('F','E','I','UMC','SS','',' ')
and course in ( @c )
-- order by 1,2,3 is not really required
), cte_gradestatistics as (
select
course,
subjectcode,
xbarplus1645sd,
xbarplussd,
xbarplus5sd,
xbar,
xbarminus5sd,
xbarminussd,
xbarminus1645sd
where course in (
select distinct course
from cte_mstmassstudents
) and subjectcode in (
select distinct subjectcode
from cte_mstmassstudents
)
-- order by 1,2 isn't required either
)
update mstmassstudents
set grade = case
when cte_mstmassstudents.marks = 0
then 'F'
when cte_mstmassstudents.marks = 100
then 'A+'
when cte_mstmassstudents.marks >= cte_gradestatistics.xbarplus1645sd
then 'A+'
when cte_mstmassstudents.marks >= cte_gradestatistics.xbarplussd
and cte_mstmassstudents.marks < cte_gradestatistics.xbarplus1645sd
then 'A'
when cte_mstmassstudents.marks >= cte_gradestatistics.xbarplus5sd
and cte_mstmassstudents.marks < cte_gradestatistics.xbarplussd
then 'B+'
when cte_mstmassstudents.marks >= cte_gradestatistics.xbar
and cte_mstmassstudents.marks < cte_gradestatistics.xbarplus5sd
then 'B'
when cte_mstmassstudents.marks >= cte_gradestatistics.xbarminus5sd
and cte_mstmassstudents.marks < cte_gradestatistics.xbar
then 'C+'
when cte_mstmassstudents.marks >= cte_gradestatistics.xbarminussd
and cte_mstmassstudents.marks < cte_gradestatistics.xbarminus5sd
then 'C'
when cte_mstmassstudents.marks >= cte_gradestatistics.xbarminus1645sd
and cte_mstmassstudents.marks < cte_gradestatistics.xbarminussd
then 'D'
when cte_mstmassstudents.marks < cte_gradestatistics.xbarminus1645sd
then 'F'
from mstmassstudents inner join (
cte_mstmassstudents inner join cte_gradestatistics
and cte_mstmassstudents.subjectcode = cte_gradestatistics.subjectcode
)
on mstmassstudents.uid = cte_mstmassstudents.uid
and cte_mstmassstudents.course = cte_mstmassstudents.course
and cte_mstmassstudents.subjectcode = cte_mstmassstudents.subjectcode
-- maybe you need this too to update only the same records selected at cte_mstmassstudents
where ems not in('F','E','I','UMC','SS','',' ')
and ims not in('F','E','I','UMC','SS','',' ')
``````
see the comment in the code...
it should be faster too..

regards

PS. i will be glad to get a feedback if this works like you want.
0

LVL 48

Assisted Solution

PortletPaul earned 333 total points
:) scary BAKADY, exactly the direction I had in mind ... as it should be faster
(and it demonstrates that using a cursor is a choice not a necessity)

Regarding gradestatistics, the code contained in the question indicates the needed calculations are being placed into a table, and judging by the existing sproc that occurs before the sproc is called. If this is true then cte_gradstatistics could be unnecessary and direct use of the table substituted in the above. Regarding the frequent casts, this is what I had in mind
``````SELECT
Course
, Subjectcode
, round(avg(castedtotal), 2)                              AS 'Avg'
, round(stdev(castedtotal), 2)                            AS 'SD'
, round(avg(castedtotal) + 1.645 * stdev(castedtotal), 2) AS 'xbarplus1645sd'
, round(avg(castedtotal) + stdev(castedtotal), 2)         AS 'xbarplussd'
, round(avg(castedtotal) + .5 * stdev(castedtotal), 2)    AS 'xbarplus5sd'
, round(avg(castedtotal), 2)                              AS 'xbar'
, round(avg(castedtotal) - .5 * stdev(castedtotal), 2)    AS 'xbarminus5sd'
, round(avg(castedtotal) - stdev(castedtotal), 2)         AS 'xbarminussd'
, round(avg(castedtotal) - 1.645 * stdev(castedtotal), 2) AS 'xbarminus1645sd'
FROM (
SELECT
Course
, Subjectcode
, cast(total AS DECIMAL(18, 5))  AS castedtotal
FROM mstmassstudents
WHERE ems NOT IN ('F', 'E', 'I', 'UMC', 'SS', '', ' ')
AND ims NOT IN ('F', 'E', 'I', 'UMC', 'SS', '', ' ')
) as subset
GROUP BY course, subjectcode
``````

@BAKADY is there any specific purpose you had in mind for the nested join?
{+an edit - sorry}
0

LVL 4

Expert Comment

@Paul: thanks...
@BAKADY is there any specific purpose you had in mind for the nested join?
@searchsanjaysharma:
i think i misunderstood the question...
i have optimize your stored procedure... it isn't bad at all, you can use it too.
But, i've noticed in PortletPaul's Comment ID#a39249318 that you generate the table "gradestatistics" with a "SELECT ... INTO ..." before the procedure runs, and you don't want to do this anymore, this because you want to nested it into the procedure, is that correct?
if this is correct, you have to add Paul's Code in my proposal for your stored procedure like this:
``````USE [dbtestresults]
GO
/****** Object:  StoredProcedure [dbo].[getgrades]    Script Date: 06/14/2013 09:51:28 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
@c varchar(200)
as
begin

with cte_mstmassstudents as (
select uid,
course,
subjectcode,
cast(total as bigint) as total
from mstmassstudents
where ems not in('F','E','I','UMC','SS','',' ')
and  ims not in('F','E','I','UMC','SS','',' ')
and course in ( @c )
-- order by 1,2,3 is not really required
), cte_gradestatistics as (
-- >>>>>  PortletPaul's proposal   <<<<< --
SELECT
Course
, Subjectcode
, round(avg(castedtotal), 2)                              AS 'Avg'
, round(stdev(castedtotal), 2)                            AS 'SD'
, round(avg(castedtotal) + 1.645 * stdev(castedtotal), 2) AS 'xbarplus1645sd'
, round(avg(castedtotal) + stdev(castedtotal), 2)         AS 'xbarplussd'
, round(avg(castedtotal) + .5 * stdev(castedtotal), 2)    AS 'xbarplus5sd'
, round(avg(castedtotal), 2)                              AS 'xbar'
, round(avg(castedtotal) - .5 * stdev(castedtotal), 2)    AS 'xbarminus5sd'
, round(avg(castedtotal) - stdev(castedtotal), 2)         AS 'xbarminussd'
, round(avg(castedtotal) - 1.645 * stdev(castedtotal), 2) AS 'xbarminus1645sd'
-- INTO gradestatistics,  is not more required
FROM (
SELECT
Course
, Subjectcode
, cast(total AS DECIMAL(18, 5))  AS castedtotal
FROM mstmassstudents
WHERE ems NOT IN ('F', 'E', 'I', 'UMC', 'SS', '', ' ')
AND ims NOT IN ('F', 'E', 'I', 'UMC', 'SS', '', ' ')
) as subset
GROUP BY course, subjectcode
)
update mstmassstudents
set grade = case
when cte_mstmassstudents.marks = 0
then 'F'
when cte_mstmassstudents.marks = 100
then 'A+'
when cte_mstmassstudents.marks >= cte_gradestatistics.xbarplus1645sd
then 'A+'
when cte_mstmassstudents.marks >= cte_gradestatistics.xbarplussd
and cte_mstmassstudents.marks < cte_gradestatistics.xbarplus1645sd
then 'A'
when cte_mstmassstudents.marks >= cte_gradestatistics.xbarplus5sd
and cte_mstmassstudents.marks < cte_gradestatistics.xbarplussd
then 'B+'
when cte_mstmassstudents.marks >= cte_gradestatistics.xbar
and cte_mstmassstudents.marks < cte_gradestatistics.xbarplus5sd
then 'B'
when cte_mstmassstudents.marks >= cte_gradestatistics.xbarminus5sd
and cte_mstmassstudents.marks < cte_gradestatistics.xbar
then 'C+'
when cte_mstmassstudents.marks >= cte_gradestatistics.xbarminussd
and cte_mstmassstudents.marks < cte_gradestatistics.xbarminus5sd
then 'C'
when cte_mstmassstudents.marks >= cte_gradestatistics.xbarminus1645sd
and cte_mstmassstudents.marks < cte_gradestatistics.xbarminussd
then 'D'
when cte_mstmassstudents.marks < cte_gradestatistics.xbarminus1645sd
then 'F'
from mstmassstudents inner join (
cte_mstmassstudents inner join cte_gradestatistics
and cte_mstmassstudents.subjectcode = cte_gradestatistics.subjectcode
)
on mstmassstudents.uid = cte_mstmassstudents.uid
and cte_mstmassstudents.course = cte_mstmassstudents.course
and cte_mstmassstudents.subjectcode = cte_mstmassstudents.subjectcode
-- maybe you need this too to update only the same records selected at cte_mstmassstudents
where ems not in('F','E','I','UMC','SS','',' ')
and ims not in('F','E','I','UMC','SS','',' ')
end
``````

If this is correct split the points between experts...

Regards
0

LVL 4

Expert Comment

@PortletPaul:
:) scary BAKADY, exactly the direction I had in mind ... as it should be faster
maybe we are both from the same school, or maybe you are my lost twin...  (just kidding...)  ;)
0

LVL 48

Accepted Solution

PortletPaul earned 333 total points
@BAKADY... hi twin :)

could you double-check those joins? e.g.
and cte_mstmassstudents.course = cte_mstmassstudents.course -- ??

I think you might mean:
``````FROM mstmassstudents
INNER JOIN cte_mstmassstudents ON mstmassstudents.uid = cte_mstmassstudents.uid
AND mstmassstudents.course = cte_mstmassstudents.course
AND mstmassstudents.subjectcode = cte_mstmassstudents.subjectcode
INNER JOIN cte_gradestatistics ON cte_mstmassstudents.course = cte_gradestatistics.icourse
AND cte_mstmassstudents.subjectcode = cte_gradestatistics.subjectcode
``````
0

LVL 4

Expert Comment

@PortletPaul: you're right, i forgot to clear "cte_" at the condition's left side and the "i" at icourse, "course" is correct...

@searchsanjaysharma: IMPORTANT!!!
Make this changes to get the code working!!!

PS. I'm posting this from EE's mobile version, this because I didn't post a fixed code.
0

Author Closing Comment

tx
0

LVL 48

Expert Comment

Hope you have that overall solution in place. Sorry you believe this is a C grade - see below

What grade should I award?
0

## Join & Write a Comment Already a member? Login.

This article explains how to reset the password of the sa account on a Microsoft SQL Server.  The steps in this article work in SQL 2005, 2008, 2008 R2, 2012, 2014 and 2016.
Ever needed a SQL 2008 Database replicated/mirrored/log shipped on another server but you can't take the downtime inflicted by initial snapshot or disconnect while T-logs are restored or mirror applied? You can use SQL Server Initialize from Backup…
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

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

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

#### Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!