• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 388
  • Last Modified:

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

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
AkAlan
Asked:
AkAlan
  • 5
  • 3
  • 2
1 Solution
 
JoeNuvoCommented:
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
 
Bhavesh ShahLead AnalysistCommented:

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
 
AkAlanAuthor Commented:
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
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
Bhavesh ShahLead AnalysistCommented:
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
 
AkAlanAuthor Commented:
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
 
AkAlanAuthor Commented:
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
 
Bhavesh ShahLead AnalysistCommented:
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
 
Bhavesh ShahLead AnalysistCommented:
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
 
Bhavesh ShahLead AnalysistCommented:
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
 
JoeNuvoCommented:
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

Transaction-level recovery for Oracle database

Veeam Explore for Oracle delivers low RTOs and RPOs with agentless transaction log backup and transaction-level recovery of Oracle databases. You can restore the database to a precise point in time, even to a specific transaction.

  • 5
  • 3
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now