Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

How to optimize this procedure.

Posted on 2013-06-14
11
Medium Priority
?
159 Views
Last Modified: 2013-06-29
Table - gradestatistics
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'
into gradestatistics
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
Comment
Question by:searchsanjaysharma
[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
  • 5
  • 4
  • 2
11 Comments
 
LVL 49

Expert Comment

by:PortletPaul
ID: 39246931
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

by:searchsanjaysharma
ID: 39246983
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 49

Expert Comment

by:PortletPaul
ID: 39247889
>>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
Prepare for your VMware VCP6-DCV exam.

Josh Coen and Jason Langer have prepared the latest edition of VCP study guide. Both authors have been working in the IT field for more than a decade, and both hold VMware certifications. This 163-page guide covers all 10 of the exam blueprint sections.

 
LVL 4

Assisted Solution

by:BAKADY
BAKADY earned 334 total points
ID: 39249101
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
  from gradestatistics
  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
     on cte_mstmassstudents.course =cte_gradestatistics.icourse
    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','',' ') 

Open in new window

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 49

Assisted Solution

by:PortletPaul
PortletPaul earned 666 total points
ID: 39249318
:) 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'
INTO gradestatistics
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

Open in new window


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

Expert Comment

by:BAKADY
ID: 39249831
@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
ALTER procedure [dbo].[getgrades]
@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
     on cte_mstmassstudents.course =cte_gradestatistics.icourse
    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

Open in new window


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

Regards
0
 
LVL 4

Expert Comment

by:BAKADY
ID: 39249847
@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 49

Accepted Solution

by:
PortletPaul earned 666 total points
ID: 39250101
@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

Open in new window

0
 
LVL 4

Expert Comment

by:BAKADY
ID: 39250213
@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

by:searchsanjaysharma
ID: 39286492
tx
0
 
LVL 49

Expert Comment

by:PortletPaul
ID: 39286528
Hope you have that overall solution in place. Sorry you believe this is a C grade - see below

What grade should I award?
C should only be given for an incomplete solution that does not fully address or answer the question. A C grade should be awarded only after the asker has replied to all expert comments, provided all requested information, tried all suggested solutions, given the experts ample time to reply, and received clarification about the answer given. The asker must justify giving a C grade and give the experts an opportunity to improve it.
0

Featured Post

Learn Veeam advantages over legacy backup

Every day, more and more legacy backup customers switch to Veeam. Technologies designed for the client-server era cannot restore any IT service running in the hybrid cloud within seconds. Learn top Veeam advantages over legacy backup and get Veeam for the price of your renewal

Question has a verified solution.

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

I have written a PowerShell script to "walk" the security structure of each SQL instance to find:         Each Login (Windows or SQL)             * Its Server Roles             * Every database to which the login is mapped             * The associated "Database User" for this …
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.
Visualize your data even better in Access queries. Given a date and a value, this lesson shows how to compare that value with the previous value, calculate the difference, and display a circle if the value is the same, an up triangle if it increased…
Want to learn how to record your desktop screen without having to use an outside camera. Click on this video and learn how to use the cool google extension called "Screencastify"! Step 1: Open a new google tab Step 2: Go to the left hand upper corn…

610 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