Solved

Can I reuse UDF returned value in a SQL Stored Procedure within the same Stored Procedure ?

Posted on 2011-03-13
10
359 Views
Last Modified: 2012-05-11
I have a sproc for returning LaborHours that has a User Defined Function for a row source which returns a sum of Fringe costs, usually 4 fringe rows for every LaborHours row in sproc. I want to then add the LaborHours with the sum of the Fringe costs as another column but I have to rerun the Function and it makes the query time go from 7 seconds to more than twice that. Seems to me if I already calculated the Fringe costs I could store them in a variable and then add the variable to the LaborHours for a total column.

Here is an excerpt from my sproc:

SELECT
hs.TS_LN_KEY
hs.LAB_CST_AMT AS TotalLaborCost,
dbo.fn_Eng_OaFringeTotals(hs.TS_LN_KEY) AS TotalFringeCosts,     --This returns the sum of fringe costs,
dbo.fn_Eng_OaFringeTotals(hs.TS_LN_KEY) + hs.LAB_CST_AMT  AS TotalCosts,   --have to rerun the function and add it to the laborcost

FROM ....etc

Open in new window


Is ther a way to assign the fringe costs to a variable and reuse it?
 
0
Comment
Question by:AkAlan
  • 5
  • 3
  • 2
10 Comments
 
LVL 11

Expert Comment

by:JoeNuvo
ID: 35125050
take a look at this one to see if any comment might good to apply for you
http://www.experts-exchange.com/Programming/Languages/.NET/ASP.NET/Q_26818174.html

and with the same way of my answer, your query should be like this

SELECT
        <other field lists>,
        Sub.TotalLaborCost * Sub.TotalFringeCosts AS TotalCosts
FROM (
      SELECT
      hs.TS_LN_KEY
      hs.LAB_CST_AMT AS TotalLaborCost,
      dbo.fn_Eng_OaFringeTotals(hs.TS_LN_KEY) AS TotalFringeCosts,
      .....
      FROM ....etc
) Sub
0
 
LVL 19

Expert Comment

by:Bhavesh Shah
ID: 35126820

Hi,

What I suggest is that, you can use temporary table.

like

SELECT
hs.TS_LN_KEY
hs.LAB_CST_AMT AS TotalLaborCost,
dbo.fn_Eng_OaFringeTotals(hs.TS_LN_KEY) AS TotalFringeCosts,     --This returns the sum of fringe costs,
dbo.fn_Eng_OaFringeTotals(hs.TS_LN_KEY) + hs.LAB_CST_AMT  AS TotalCosts,   --have to rerun the function and add it to the laborcost

INTO #TempTable

FROM ....etc



If above query is inside procedure then you no need to drop that table explicitly.

else you can use

DROP TABLE #TempTable



- Bhavesh
0
 
LVL 6

Author Comment

by:AkAlan
ID: 35128963
Joe, that looks promising, I'll try it out later today.

Brichsoft, I don't see how your solution keeps from running the same function twice.
0
 
LVL 19

Expert Comment

by:Bhavesh Shah
ID: 35135335
Hi,

See.I'm assuming, you calling one function twice and that you wanted to avoid..

If so then.....

This will be your 1st Query.

SELECT
hs.TS_LN_KEY,
hs.LAB_CST_AMT AS TotalLaborCost,
dbo.fn_Eng_OaFringeTotals(hs.TS_LN_KEY) AS TotalFringeCosts,     --This returns the sum of fringe costs,
Other columns

into #Temp

FROM ....etc


This will be your 2nd Query.

SELECT TS_LN_KEY, TotalLaborCost, (TotalLaborCost + TotalFringeCosts) TotalCosts
FROM #Temp


- Bhavesh
0
 
LVL 6

Author Comment

by:AkAlan
ID: 35139197
Bhavesh, thanks for clearing that up. I still have not been able to play with either soultion, I will soon and see which one works best.

Cheers, Alan
0
Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 6

Author Comment

by:AkAlan
ID: 35200875
Joe, I tried your solution and while it worked ok, it didn't really speed the time the query took to run, which is what I am looking for.

Bhavesh, I'm not familiar with temp tables so maybe there is something more that I need to do but when I try the following code, I get "There is already an object named '#Temp' in the database."


Alter PROCEDURE [dbo].[spSelectENG_OverAndAboveSummary_Test]
(@OA_Nr varchar(5) = NULL)
--@Engineer varchar(6) = NULL)    --Must use a varchar to use wildcard, 


AS 
CREATE TABLE #Temp(OaNumber char(5),ProjectDescription Varchar(MAX),tp money,tt money, tl Money)
SELECT				oap.OANumber,
				    oap.ProjectDescription,
				    dbo.fn_Eng_OaPurchaceTotals(oap.OANumber) AS TotalPurchases, 
				    dbo.fn_Eng_OaTravelTotals(oap.OANumber) AS TotalTravel,
				    dbo.fn_Eng_OaLaborTotals(oap.OANumber) AS TotalLabor
				    
				    INTO #Temp
					
				    FROM 
					
				dbo.ENG_OverAndAboveProjects    oap 
				
				WHERE oap.OANumber = @OA_Nr 
					
				SELECT oap.OANumber FROM #Temp  --There is already an object named '#Temp' in the database.

Open in new window

                       
0
 
LVL 19

Expert Comment

by:Bhavesh Shah
ID: 35204203
Hi Alan,

As you created

CREATE TABLE #Temp(OaNumber char(5),ProjectDescription Varchar(MAX),tp money,tt money, tl Money)

so you no need to use INTO #Temp

you need to use below query.


- Bhavesh
Alter PROCEDURE [dbo].[spSelectENG_OverAndAboveSummary_Test]
(@OA_Nr varchar(5) = NULL)
--@Engineer varchar(6) = NULL)    --Must use a varchar to use wildcard, 


AS 
CREATE TABLE #Temp(OaNumber char(5),ProjectDescription Varchar(MAX),tp money,tt money, tl Money)
insert into #Temp
SELECT                          oap.OANumber,
                                    oap.ProjectDescription,
                                    dbo.fn_Eng_OaPurchaceTotals(oap.OANumber) AS TotalPurchases, 
                                    dbo.fn_Eng_OaTravelTotals(oap.OANumber) AS TotalTravel,
                                    dbo.fn_Eng_OaLaborTotals(oap.OANumber) AS TotalLabor
                                    
                                     
                                        
                                    FROM 
                                        
                                dbo.ENG_OverAndAboveProjects    oap 
                                
                                WHERE oap.OANumber = @OA_Nr 
                                        
                                SELECT oap.OANumber FROM #Temp  --There is already an object named '#Temp' in the database.

Open in new window

0
 
LVL 19

Accepted Solution

by:
Bhavesh Shah earned 500 total points
ID: 35204263
Hi,

Just for information.

Below query will create physical table in database.

SELECT
            oap.OANumber,
            oap.ProjectDescription,
            dbo.fn_Eng_OaPurchaceTotals(oap.OANumber) AS TotalPurchases,
            dbo.fn_Eng_OaTravelTotals(oap.OANumber) AS TotalTravel,
            dbo.fn_Eng_OaLaborTotals(oap.OANumber) AS TotalLabor
 INTO NewTable
 FROM
           dbo.ENG_OverAndAboveProjects    oap
 WHERE oap.OANumber = @OA_Nr



Below query will create temporary table in database, this table will create in tempdb database

SELECT
            oap.OANumber,
            oap.ProjectDescription,
            dbo.fn_Eng_OaPurchaceTotals(oap.OANumber) AS TotalPurchases,
            dbo.fn_Eng_OaTravelTotals(oap.OANumber) AS TotalTravel,
            dbo.fn_Eng_OaLaborTotals(oap.OANumber) AS TotalLabor
 INTO #NewTable
 FROM
           dbo.ENG_OverAndAboveProjects    oap
 WHERE oap.OANumber = @OA_Nr

 

More information on temporary table.

Types of Temporary tables

There are two types of temporary data types. They are namely Local and global. Let me first give you and example to start the temporary table. Following example is taken from Books on Line of Microsoft® SQL Server™ 2000.

"The two types of temporary tables, local and global, differ from each other in their names, their visibility, and their availability. Local temporary tables have a single number sign (#) as the first character of their names; they are visible only to the current connection for the user; and they are deleted when the user disconnects from instances of Microsoft® SQL Server™ 2000. Global temporary tables have two number signs (##) as the first characters of their names; they are visible to any user after they are created; and they are deleted when all users referencing the table disconnect from SQL Server" 1

"For example, if you create a table named employees, the table can be used by any person who has the security permissions in the database to use it, until the table is deleted. If you create a local temporary table named #employees, you are the only person who can work with the table, and it is deleted when you disconnect. If you create a global temporary table named ##employees, any user in the database can work with this table. If no other user works with this table after you create it, the table is deleted when you disconnect. If another user works with the table after you create it, SQL Server deletes it when both of you disconnect."2

Note: 1,2 above is taken from the book on line sub heading Creating and Modifying

Unlike in the access days, you do not have to delete these temporary tables manually, instead you can rely SQL Server to do it automatically.
0
 
LVL 19

Expert Comment

by:Bhavesh Shah
ID: 35204273
Hi,

I am not sure, this will improve performance.
If you can share your function code then, might experts can give you suggestion for better approach.


- Bhavesh
0
 
LVL 11

Expert Comment

by:JoeNuvo
ID: 35204312
If your function doesn't contain complex query/query working with huge dataset.
Reduce 1 call may not effect much of performance. (in profiler, CPU maybe the same, but maybe reduce READ)
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

If you find yourself in this situation “I have used SELECT DISTINCT but I’m getting duplicates” then I'm sorry to say you are using the wrong SQL technique as it only does one thing which is: produces whole rows that are unique. If the results you a…
This article describes how to use the timestamp of existing data in a database to allow Tableau to calculate the prior work day instead of relying on case statements or if statements to calculate the days of the week.
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…

758 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

25 Experts available now in Live!

Get 1:1 Help Now