Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2000 Forums
 Transact-SQL (2000)
 Code Revision

Author  Topic 

mk_garg20
Constraint Violating Yak Guru

343 Posts

Posted - 2004-09-06 : 01:17:09
Hello All,
Can i improve following code.

CREATE PROCEDURE Sales (@StartDate AS VarChar(10), @EndDate AS VarChar(10))
AS

CREATE TABLE #JobLaserMail
(
JobNo VARCHAR(10) PRIMARY KEY,
TotLaserImages INT,
TotalMailpacks INT
)

CREATE TABLE #JobAmount
(
JobNo VARCHAR(10) PRIMARY KEY,
JobAmount INT
)

CREATE TABLE #AM
(
JobNo VARCHAR(10),
CompanyID INT,
ResID INT,
Name VARCHAR(50),
RelationTypeID VARCHAR(4)
)

CREATE TABLE #AE
(
JobNo VARCHAR(10),
CompanyID INT,
ResID INT,
Name VARCHAR(50),
RelationTypeID VARCHAR(4)
)

--Getting CDS Relation AM for each Job
INSERT INTO #AM
SELECT ContractID AS JobNo,CompanyID,Relation.ResID,LTRIM(RTRIM(Res.Name)),RelationTypeID
FROM Relation,Res
WHERE Relation.ResID=Res.ResID
AND ContractID IN
(SELECT DISTINCT JobNo FROM JobInvoice
WHERE InvoiceDate >= CONVERT(DATETIME, @StartDate, 103)AND
InvoiceDate <= CONVERT(DATETIME, @EndDate, 103)+1) AND RelationTypeID='CR4'

--Getting CDS Relation AE for each Job
INSERT INTO #AE
SELECT ContractID AS JobNo,CompanyID,Relation.ResID,LTRIM(RTRIM(Res.Name)),RelationTypeID
FROM Relation,Res
WHERE Relation.ResID=Res.ResID
AND ContractID IN
(SELECT DISTINCT JobNo FROM JobInvoice
WHERE InvoiceDate >= CONVERT(DATETIME, @StartDate, 103)AND
InvoiceDate <= CONVERT(DATETIME, @EndDate, 103)+1) AND RelationTypeID='CR5'

--Getting Total Laser imasges and mailpacks for each Job
INSERT INTO #JobLaserMail
SELECT JobInvoice.JobNo,sum(ReconcileJobProductComponent.ActLaserTotalA4Images) AS 'TotLaserImages',
sum(ReconcileJobProductComponent.ActMailMachineMailPacks) AS 'TotalMailpacks'
FROM JobInvoice LEFT OUTER JOIN ReconcileJobProductComponent on JobInvoice.JobNo=ReconcileJobProductComponent.JobNo
WHERE JobInvoice.InvoiceDate >= CONVERT(DATETIME, @StartDate, 103)AND JobInvoice.InvoiceDate <= CONVERT(DATETIME, @EndDate, 103)+1
GROUP BY JobInvoice.JobNo

--Getting Total value of each Job
INSERT INTO #JobAmount
SELECT JobInvoice.JobNo, sum(SOP.DOCAMNT) AS 'JobAmount'
FROM JobInvoice LEFT JOIN SOP302 AS SOP on JobInvoice.InvoiceNo=SOP.SOPNUMBE
WHERE JobInvoice.InvoiceDate >= CONVERT(DATETIME, @StartDate, 103)AND JobInvoice.InvoiceDate <= CONVERT(DATETIME, @EndDate, 103)+1
GROUP BY JobInvoice.JobNo
ORDER BY JobInvoice.JobNo


CREATE TABLE #WorkingTable (
JobNo VARCHAR(10),
CompanyID INT,
Name VARCHAR(50),
list VARCHAR(1000))

INSERT INTO #WorkingTable (JobNo,CompanyID,Name)
SELECT JobNo,CompanyID,Name
FROM #AE
ORDER BY JobNo,Name

DECLARE
@list VARCHAR(1000),
@lastJobNo VARCHAR(10),
@lastCompanyID INT

SELECT
@list = '',
@lastJobNo = '',
@lastCompanyID = 0

UPDATE
#WorkingTable
SET
@list = list = CASE
WHEN @lastJobNo <> JobNo OR @lastCompanyID<>CompanyID THEN Name
else @list + ',' + Name
end,
@lastJobNo = JobNo,@lastCompanyID=CompanyID

CREATE TABLE #final (JobNo VARCHAR(10), CompanyID int,AM VARCHAR(1000), AE VARCHAR(1000))
INSERT INTO #final
SELECT #WorkingTable.JobNo, #WorkingTable.CompanyID,max(#AM.Name), max(list) as list
FROM #WorkingTable LEFT JOIN #AM ON #WorkingTable.JobNo=#AM.JobNo
GROUP BY #WorkingTable.JobNo,#WorkingTable.CompanyID
ORDER BY #WorkingTable.JobNo,#WorkingTable.CompanyID

UPDATE #final
Set
AM = CASE WHEN CHARINDEX(',',AE)>0 THEN LEFT(AE,CHARINDEX(',',AE)-1) else AE end,
AE = CASE WHEN CHARINDEX(',',AE)>0 THEN RIGHT(AE,LEN(AE) - CHARINDEX(',',AE)) else NULL end
FROM #final
Where AM is NULL

SELECT DISTINCT JobInvoice.JobNo,
Job.JobName,
Company.CompanyName,
#JobAmount.JobAmount,
#JobLaserMail.TotLaserImages,#JobLaserMail.TotalMailpacks,
#final.AM,#final.AE
FROM JobInvoice
LEFT JOIN Job ON JobInvoice.JobNo=Job.JobNo
LEFT JOIN #JobAmount ON JobInvoice.JobNo=#JobAmount.JobNo
LEFT JOIN #JobLaserMail ON JobInvoice.JobNo=#JobLaserMail.JobNo
RIGHT JOIN #final ON JobInvoice.JobNo=#final.JobNo
INNER JOIN Company on #final.CompanyID=Company.CompanyID
WHERE JobInvoice.InvoiceDate >= CONVERT(DATETIME, @StartDate, 103)AND JobInvoice.InvoiceDate <= CONVERT(DATETIME, @EndDate, 103)+1
ORDER BY #Final.AM, Company.CompanyName, JobInvoice.JobNo


DROP TABLE #AM
DROP TABLE #AE
DROP TABLE #JobLaserMail
DROP TABLE #JobAmount
DROP TABLE #final
DROP TABLE #WorkingTable


Thanks

mk_garg

timmy
Master Smack Fu Yak Hacker

1242 Posts

Posted - 2004-09-06 : 01:42:30
I would swap your SELECT DISTINCT sub-queries for JOIN's for a start.
Go to Top of Page

mk_garg20
Constraint Violating Yak Guru

343 Posts

Posted - 2004-09-06 : 02:32:00
if you mean JOIN will faster than IN.
I agree with you.

What else?

Thanks


mk_garg
Go to Top of Page

mohdowais
Sheikh of Yak Knowledge

1456 Posts

Posted - 2004-09-06 : 04:11:14
I am pretty much sure that the repeated conversion of character strings to datetime is quite a performance hit. Why dont you pass in the date parameters as a datetime value? Even if you must do the conversion, do it once at the top in another set of variables and then use those datetime variables in the queries.

If you dont have too many rows in the temp tables, you will probably benefit from using table variables instead of temp tables.

And like timmy suggested, change the IN clauses to either INNER JOINs or WHERE EXISTS.

Another hint, turn on "Show Execution plan" and the run the query so you can see where your real bottlenecks are. I usually run the old version of the query and the new optimised version in different windows, so I can see where the performance gains are coming from.

OS
Go to Top of Page

mk_garg20
Constraint Violating Yak Guru

343 Posts

Posted - 2004-09-06 : 18:31:50
Hi OS,
As you suggested:-
I will do conversion only once.
I can not use table variables.(Using SQL SERVER 7.0 )
I will use INNER JOINs.

Thanks

mk_garg
Go to Top of Page

mk_garg20
Constraint Violating Yak Guru

343 Posts

Posted - 2004-09-06 : 19:02:45
Which one will be faster INNER JOINs or WHERE EXISTS.

I want to use SET NOCOUNT ON and SET NOCOUNT OFF. Where i should place these statements in stored procedure.

Thanks

mk_garg
Go to Top of Page

spirit1
Cybernetic Yak Master

11752 Posts

Posted - 2004-09-07 : 08:41:02
i think that in your case joins will be faster (less table scans). but ultimatly you'd need to see execution plans.

SET NOCOUNT ON before the insert or update so you don't get bac the message: n rows have been affected.
SET NOCOUNT ON after the insert or update.


Go with the flow & have fun! Else fight the flow
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2004-09-09 : 23:48:15
I always declare a Primary Key on temporary tables - suprising how often this speeds things up significant;y, even if there are only a few rows in the temp. table. (c.f. #AM and #AE, and #WorkingTable)

I put SET NOCOUNT ON as the very first statement in all my SProcs. And SET ARITHABORT ON and SET XACT_ABORT ON.

#AM and #AE could be combined (they've both got a RelationTypeID column anyway), that would save one query - but might slow down the actions on the resulting temporary table, which will have to have an extra "WHERE RelationTypeID='XXX' condition.

Why have both #AE and #WorkingTable?


Is
InvoiceDate <= CONVERT(DATETIME, @EndDate, 103)+1
going to give you what you want? This is midnight at the end of the @endDate day - prehaps you should use LESS THAN - rahter than LESS THAN OR EQUAL (I'd set these as datetime, and sort out making @EndDate be the correctly adjusted value, at the top of the SProc as mohdowais said)

#JobLaserMail (and probably some others) is only used in the final SELECT statement - is it worth making a temporary table, rather than just referencing the data in that final SELECT?

Kristen
Go to Top of Page

mk_garg20
Constraint Violating Yak Guru

343 Posts

Posted - 2004-09-10 : 01:34:39
quote:
I put SET NOCOUNT ON as the very first statement in all my SProcs. And SET ARITHABORT ON and SET XACT_ABORT ON


Did that. Should i turn it OFFin the end

quote:
InvoiceDate <= CONVERT(DATETIME, @EndDate, 103)+1


Corrected my mistake(<=) to (=)
Converting to datetime only once.

quote:
Why have both #AE and #WorkingTable?

Using #AE only

quote:
#JobLaserMail (and probably some others) is only used in the final SELECT statement - is it worth making a temporary table, rather than just referencing the data in that final SELECT?


Doing alot of caluclations

mk_garg
Go to Top of Page
   

- Advertisement -