January 3, 2017 at 8:28 pm
Hi All, I have the following T-SQL;
With
CTECTD1(dossierno,custno,regnno,costcentre,odometer,fuel,repairs,leasecharges,tollroadcharges,rucrego,otherexpenses,accident,managment,litersper,litersavg)
AS
(
SELECT
f.DossierNo as [DossierNo]
,f.CustNo
,f.RegnNo
,d.CostCentre
,MAX(f.Odo) as [Odometer]
,SUM(CASE WHEN l.[InvSeq] in ('70') THEN CAST(ROUND([CTD_Amount],2) AS INT) ELSE '' END) as [Fuel/Oil]
,SUM(CASE WHEN l.[InvSeq] in ('40','45') THEN CAST(ROUND([CTD_Amount],2) AS INT) ELSE '' END) as [Repairs/Maintenance]
,SUM(CASE WHEN l.[InvSeq] in ('35') THEN CAST(ROUND([CTD_Amount],2) AS INT) ELSE '' END) as [LeaseCharges]
,SUM(CASE WHEN l.[InvSeq] in ('65') THEN CAST(ROUND([CTD_Amount],2) AS INT) ELSE '' END) as [TollRoadCharges]
,SUM(CASE WHEN l.[InvSeq] in ('60','61') THEN CAST(ROUND([CTD_Amount],2) AS INT) ELSE '' END) as [RUC/Rego]
,SUM(CASE WHEN l.[InvSeq] in ('10','20','21','22','23','80','90') THEN CAST(ROUND([CTD_Amount],2) AS INT) ELSE '' END) as [OtherExpenses]
,SUM(CASE WHEN l.[InvSeq] in ('50') THEN CAST(ROUND([CTD_Amount],2) AS INT) ELSE '' END) as [AccidentInsurance]
,SUM(CASE WHEN l.[InvSeq] in ('30','31') THEN CAST(ROUND([CTD_Amount],2) AS INT) ELSE '' END) as [ManagementCharges]
--,SUM(i.NetAmount) as [Total]
--,SUM(i.NetAmount)/NULLIF((MAX(f.odo)),0) as [TotalCentsPerKm]
,0 as [LitresPerVehicle]
,0 as [LitresNationalAverage]
FROM [FPNZ_Extra].[tblFleetSmartVehicleLifetoDate] l
INNER JOIN [FPNZ_Extra].[tblFuelTran] f
ON f.dossierNo = l.dossierNo and f.CustNo = l.CustNo and f.RegnNo = l.RegnNo
INNER JOIN [FPNZ_Extra].[vwDataDossier] d
ON f.DossierNo = d.DossierNo and f.RegnNo = d.RegnNo and d.CustNo = f.CustNo
--INNER JOIN [FPNZ_Extra].[tblFLEETSMARTCustomerReportDistribution] c
--on f.custno = c.[CustNo]and l.CustNo = c.CustNo
WHERE
IsOdoValid = '1'
AND d.costcentre != ' '
--AND c.ReportName = 'DM Vehicle Analysis'
--AND l.CustNo in ('300562','309032','312832','316984','317264','317671','381297','381612')
GROUP BY f.custno,f.regnno,d.costcentre,f.DossierNo,l.custno
)
,
CTECTD2(costcentre,custno,dossierno,regnno,modelyear,vehicledesc,drivername,total,totalcents,span)
as
(
SELECT
i.costCentre as [CostCentre]
,i.CustNo
,i.DossierNo as [DossierNo]
,i.regnno
,d.ModelYear as [ModelYear]
,i.VehicleDesc
,i.DriverName
,SUM(i.NetAmount) as [Total]
,SUM(i.NetAmount)/NULLIF((MAX(f.odo)),0) as [TotalCentsPerKm]
,MAX(f.odo) - MAX(sub.[odo]) as [Span(Kms)]
--,MAX(f.odo) - MAX(sub.[odo]) as [TotalKmsToDate]
FROM [FPNZ_Extra].[vwDataDossier] d
INNER JOIN [FPNZ_Extra].[tblInvoiceItemData] i
ON d.DossierNo = i.DossierNo
INNER JOIN [FPNZ_Extra].[tblFLEETSMARTCustomerReportDistribution] c
on d.custno = c.[CustNo]
INNER JOIN [FPNZ_Extra].[tblFuelTran] f
ON f.dossierNo = i.DossierNo
LEFT OUTER JOIN
(SELECT MIN(f1.odo)as [odo],regnno, MIN(f1.LastOdoDate) as [oldest]
FROM [FPNZ_Extra].[tblFuelTran] f1
WHERE
IsOdoValid = '1'
AND f1.regnno != ' '
GROUP BY RegnNo
)as sub
ON f.regnno = sub.RegnNo
WHERE
i.costcentre != ' '
AND c.ReportName = 'DM Vehicle Analysis'
--AND i.CustNo in ('300562','309032','312832','316984','317264','317671','381297','381612')
GROUP BY i.CustNo, i.costcentre, i.regnno, i.DossierNo, d.ModelYear,i.VehicleDesc,i.DriverName
)
,
CTECTD4(costcentre,custno,dossierno,regnno,fuel,repairs,leasecharges,tollroadcharges,rucrego,otherexpenses,accident,managment,total)
AS
(
--------------Vehicle Analysis BPT
SELECT
i.costCentre as [CostCentre]
,i.CustNo
,i.DossierNo as [DossierNo]
,i.regnno
,SUM(CASE WHEN [InvSeq] in ('70') THEN NetAmount ELSE '' END) as [Fuel/Oil]
,SUM(CASE WHEN [InvSeq] in ('40','45') THEN NetAmount ELSE '' END) as [Repairs/Maintenance]
,SUM(CASE WHEN [InvSeq] in ('35') THEN NetAmount ELSE '' END) as [LeaseCharges]
,SUM(CASE WHEN [InvSeq] in ('65') THEN NetAmount ELSE '' END) as [TollRoadCharges]
,SUM(CASE WHEN [InvSeq] in ('60','61') THEN NetAmount ELSE '' END) as [RUC/Rego]
,SUM(CASE WHEN [InvSeq] in ('10','20','21','22','23','80','90') THEN NetAmount ELSE '' END) as [OtherExpenses]
,SUM(CASE WHEN [InvSeq] in ('50') THEN NetAmount ELSE '' END) as [AccidentInsurance]
,SUM(CASE WHEN [InvSeq] in ('30','31') THEN NetAmount ELSE '' END) as [ManagementCharges]
,SUM(i.NetAmount) as [Total]
FROM [FPNZ_Extra].[tblFuelTran] f
INNER JOIN [FPNZ_Extra].[tblInvoiceItemData] i
ON f.DossierNo = i.DossierNo and f.RegnNo = i.RegnNo
INNER JOIN [FPNZ_Extra].[tblFLEETSMARTCustomerReportDistribution] c
on f.custno = c.[CustNo]
WHERE DATEPART(m, f.[FuelTranDate]) = DATEPART(m, DATEADD(m, -2, getdate())) AND DATEPART(yyyy, f.[FuelTranDate] ) = DATEPART(yyyy, DATEADD(m, -2, getdate()))
AND IsOdoValid = '1'
AND i.costcentre != ' '
AND c.ReportName = 'DM Vehicle Analysis'
--AND i.CustNo in ('300562','309032','312832','316984','317264','317671','381297','381612')
GROUP BY i.CustNo, i.costcentre, i.regnno, i.DossierNo,i.VehicleDesc,i.DriverName
)
,
CTECTD5 (custno,dossierno,Regnno,c02)
AS
(
SELECT f1.CustNo, f1.DossierNo,f1.RegnNo, sum([C02])
FROM
(SELECT CustNo, dossierno,regnno,
CASE WHEN Product = 'Diesel' THEN ISNULL(CAST(2.70 * (SUM([Quantity]) / NULLIF(1000,0)) AS DECIMAL (18,2)),0)
WHEN Product = 'Premium' THEN ISNULL(CAST(ROUND(2.36 * (SUM([Quantity]) / NULLIF(1000,0)),2) AS DECIMAL (18,2)),0)
WHEN Product = 'Regular' THEN ISNULL(CAST(ROUND(2.34 * (SUM([Quantity]) / NULLIF(1000,0)),2) AS DECIMAL (18,2)),0) END AS [C02]
FROM [FPNZ_Extra].[tblFuelTran]
WHERE
Producttype = 'Fuel'
AND Product in ('Diesel','Premium','Regular')
AND quantity is not null
AND odo is not null
AND odo != ' '
GROUP BY custno,DossierNo, RegnNo, Product
) f1
GROUP BY f1.CustNo, f1.DossierNo,f1.RegnNo
)
SELECT 'CTD' as [CTDRecType]
,d1.costcentre
, D2.regnno
, D2.modelyear
, d2.vehicledesc
, d2.drivername
, d1.odometer
, d2.span
, (d1.fuel + d4.fuel) [Fuel/Oil]
, (d1.repairs + d4.repairs) [Repairs]
, (d1.leasecharges + d4.leasecharges) [LeaseCharges]
, (d1.tollroadcharges + d4.tollroadcharges) [TollCharges]
, (d1.rucrego + d4.rucrego) [RUC/Rego]
, (d1.otherexpenses + d4.otherexpenses) [OtherExpenses]
, (d1.accident + d4.accident) [Accident]
, (d1.managment + d4.managment) [Managment]
,(d2.total + d4.total) [TotalexclGST]
, d2.totalcents [TotalCents]
, d1.litersper [Litres/100Km]
, d1.litersavg [Litres/National]
--, d5.c02 [C02]
, d2.span as [TotalKms]
FROM CTECTD1 D1
JOIN CTECTD2 D2
ON D1.CostCentre = D2.costcentre and d1.dossierno = d2.dossierno and d1.regnno = d2.regnno
JOIN CTECTD4 D4
ON D2.CostCentre = D4.costcentre and d2.regnno = d4.regnno
--JOIN CTECTD5 D5
--ON D1.Custno = D5.Custno and d1.regnno = d5.regnno
This generates calculated columns for all records in a year.It used to take between 2-3 hours to finish running, I have improved the performance by adding some clustered and non clustered index's on the tables. But in the query planner it has a nested loop with a no join predicate, see attached image.
Does anyone have any suggestions? thanks.
[/url][/img]
January 4, 2017 at 2:06 am
Run the code of the three relevant CTE's separately to identify which one is responsible, then doublecheck the execution plan. The optimiser throws up false positives from time to time, and this might be one of them.
The code references a number of tables / views multiple times. There's almost certainly scope for significant improvement. Have you considered hiring a consultant for a while for some hands-on training?
For fast, accurate and documented assistance in answering your questions, please read this article.
Understanding and using APPLY, (I) and (II) Paul White
Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden
January 4, 2017 at 4:40 am
How about trying temporary tables with indexes?
- Damian
January 4, 2017 at 3:06 pm
I found and fixed the problem in the CTE's I added more joins and this removed the No Join Predicate, thanks for the replies.
Viewing 4 posts - 1 through 3 (of 3 total)
You must be logged in to reply to this topic. Login to reply