Dear Team
Below is my Stored Procedure. It is taking very long (6-10) minutes to execute the part when I did the LEFT join. Attached here is the link to the backup of the database on google drive : https://drive.google.com/file/d/0B5nQIsvTifixUmxXRkwtQW1VWkU/edit?usp=sharing
Please use the SP Script and DB to reproduce my situation
USE [SATURNRPT]
GO
/****** Object: StoredProcedure [dbo].[PNGudp_Reports_GuardInvoicingBreakUp] Script Date: 08/16/2014 08:51:41 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[PNGudp_Reports_GuardInvoicingBreakUp]
(
@FROMDATE DATE,
@TODATE DATE,
@BillingPattern nvarchar(1)='B',
@LocationAutoId int,
@AreaID nvarchar(max)='*',
@ClientCode nvarchar(max)='*'
)
AS
SET NOCOUNT ON
-------------------------------------------------------
-- STEP 0. Extract Billing Pattern
-------------------------------------------------------
DECLARE @TmpSalesOrderInit TABLE
(
ClientCode nvarchar(16),
SoNo nvarchar(32),
BillingPattern nvarchar
)
INSERT INTO @TmpSalesOrderInit
SELECT tt.ClientCode, tt.SoNo,Substring(tt.BillingPattern,1,1)
FROM mstSaleOrder tt
INNER JOIN
(SELECT SoNo , MAX(SoAmendNo) AS MaxSoAmendNo
FROM mstSaleOrder WHERE SoStatus='AUTHORIZED' AND ClientCode NOT LIKE '%INTERNAL%'
GROUP BY SoNo) groupedtt
ON tt.SoNo = groupedtt.SoNo
AND tt.SoAmendNo = groupedtt.MaxSoAmendNo
DECLARE @TmpSalesOrder TABLE
(
ClientCode nvarchar(16),
SoNo nvarchar(32),
BillingPattern nvarchar
)
IF @BillingPattern='B'
BEGIN
INSERT INTO @TmpSalesOrder
Select * from @TmpSalesOrderInit
END
ELSE
BEGIN
INSERT INTO @TmpSalesOrder
Select * from @TmpSalesOrderInit WHERE BillingPattern=@BillingPattern
END
-------------------------------------------------------
-- STEP 1. Extract Deployment Details 1st Step
-------------------------------------------------------
DECLARE @TmpSoDeptShift TABLE
(
SoNo nvarchar(32),
SoLineNo int,
PayRatePerHour numeric(18,2),
ChargeRatePerHour numeric(18,2),
ShiftHours numeric(18,2),
NoOfPersons int
)
INSERT INTO @TmpSoDeptShift
SELECT distinct tt.SoNo,SoLineNo,
CASE
WHEN tt.MonPayRate <> 0 then tt.MonPayRate
WHEN tt.TuePayRate <> 0 then tt.TuePayRate
WHEN tt.WedPayRate <> 0 then tt.WedPayRate
WHEN tt.ThuPayRate <> 0 then tt.ThuPayRate
WHEN tt.FriPayRate <> 0 then tt.FriPayRate
WHEN tt.SatPayRate <> 0 then tt.SatPayRate
WHEN tt.SunPayRate <> 0 then tt.SunPayRate
ELSE 0 END As PayRatePerHour,
CASE
WHEN tt.MonSellingRate <> 0 then tt.MonSellingRate
WHEN tt.TueSellingRate <> 0 then tt.TueSellingRate
WHEN tt.WedSellingRate <> 0 then tt.WedSellingRate
WHEN tt.ThuSellingRate <> 0 then tt.ThuSellingRate
WHEN tt.FriSellingRate <> 0 then tt.FriSellingRate
WHEN tt.SatSellingRate <> 0 then tt.SatSellingRate
WHEN tt.SunSellingRate <> 0 then tt.SunSellingRate
ELSE 0 END As ChargeRatePerHour,
CASE
WHEN DATEDIFF(HOUR,MonTimeFrom,MonTimeTo) <> 0 then ABS(DATEDIFF(HOUR,MonTimeFrom,MonTimeTo))
WHEN DATEDIFF(HOUR,TueTimeFrom,TueTimeTo) <> 0 then ABS(DATEDIFF(HOUR,TueTimeFrom,TueTimeTo))
WHEN DATEDIFF(HOUR,WedTimeFrom,WedTimeTo) <> 0 then ABS(DATEDIFF(HOUR,WedTimeFrom,WedTimeTo))
WHEN DATEDIFF(HOUR,ThuTimeFrom,ThuTimeTo) <> 0 then ABS(DATEDIFF(HOUR,ThuTimeFrom,ThuTimeTo))
WHEN DATEDIFF(HOUR,FriTimeFrom,FriTimeTo) <> 0 then ABS(DATEDIFF(HOUR,FriTimeFrom,FriTimeTo))
WHEN DATEDIFF(HOUR,SatTimeFrom,SatTimeTo) <> 0 then ABS(DATEDIFF(HOUR,SatTimeFrom,SatTimeTo))
WHEN DATEDIFF(HOUR,SunTimeFrom,SunTimeTo) <> 0 then ABS(DATEDIFF(HOUR,SunTimeFrom,SunTimeTo))
ELSE 0 END As ShiftHours,
CASE
WHEN tt.MonNoOfPersons <> 0 then tt.MonNoOfPersons
WHEN tt.TueNoOfPersons <> 0 then tt.TueNoOfPersons
WHEN tt.WedNoOfPersons <> 0 then tt.WedNoOfPersons
WHEN tt.ThuNoOfPersons <> 0 then tt.ThuNoOfPersons
WHEN tt.FriNoOfPersons <> 0 then tt.FriNoOfPersons
WHEN tt.SatNoOfPersons <> 0 then tt.SatNoOfPersons
WHEN tt.SunNoOfPersons <> 0 then tt.SunNoOfPersons
ELSE 0 END As NoOfPersons
FROM mstSaleOrderDeptShift tt
INNER JOIN
(SELECT SoNo , MAX(SoAmendNo) AS MaxSoAmendNo
FROM mstSaleOrderDeptShift
GROUP BY SoNo) groupedtt
ON tt.SoNo = groupedtt.SoNo
AND tt.SoAmendNo = groupedtt.MaxSoAmendNo
-------------------------------------------------------
-- STEP 2. Get Number Public Holidays and the Days in Month
-------------------------------------------------------
Declare @TmpTrnHoliday TABLE
(
HolidayDate Date,
HolidayCode nvarchar(10)
)
Insert @TmpTrnHoliday
exec PNGudp_Reports_GetPublicHolidays @FROMDATE,@TODATE
select COUNT(*) as Cnt into #TmpCnt
from @TmpTrnHoliday
insert into #TmpCnt
select dbo.PNG_GetDaysInMonth(GetDate())
--select SUM(cnt) from #TmpCnt
-------------------------------------------------------
-- STEP 2. Extract Deployment Details 2nd Step
-------------------------------------------------------
DECLARE @TmpDeployment TABLE
(
SoNo nvarchar(32),
SoLineNo int,
PayRatePerHour numeric(18,2),
ChargeRatePerHour numeric(18,2),
ShiftHours numeric(18,2),
NoOfPersons int,
MonthlyRate money
)
INSERT INTO @TmpDeployment
select T.*,CASE WHEN M.BillingPattern='F' THEN (T.NoOfPersons*12*377*T.ChargeRatePerHour)/12 ELSE T.NoOfPersons*12*(select SUM(cnt) from #TmpCnt) *T.ChargeRatePerHour END as MonthlyRate from @TmpSoDeptShift T
INNER JOIN @TmpSalesOrder M on T.SoNo=M.SoNo
---------------------------------
-- STEP 1. Extract the Contracted Hours
-------------------------------------
DECLARE @TmpContract TABLE
(
LocationAutoId int,
LocationDesc nvarchar(50),
AreaID nvarchar(16),
ClientCode nvarchar(16),
ClientName nvarchar(100),
BillingPattern char(1),
AsmtID udtAssmtID,
AsmtName nvarchar(100),
DutyDate date,
DayNbr int,
PostAutoID Numeric(18,0),
PostDesc nvarchar(200),
ChargeRatePerHour numeric(18,2),
MonthlyRate Money,
ContractedHours int
)
IF @LocationAutoId = 0
BEGIN
INSERT INTO @TmpContract
SELECT C.LocationAutoId, dbo.mstLocation.LocationDesc, dbo.mstSaleClientDetails.AreaID, C.ClientCode, dbo.mstSaleClient.ClientName,M.BillingPattern , C.AsmtID,
dbo.mstSaleClientDetails.AsmtName, C.Dutydate, DatePart(Day,c.DutyDate) as DayNbr, C.PostAutoID, C.PostDesc, X.ChargeRatePerHour,X.MonthlyRate,SUM(C.ContractedHrs)
FROM dbo.tblContractHrs C INNER JOIN
dbo.mstSaleClient ON C.ClientCode = dbo.mstSaleClient.ClientCode
INNER Join @TmpSalesOrder M ON C.ClientCode=M.ClientCode and C.SoNo=M.SoNo
INNER JOIN dbo.mstSaleClientDetails ON C.ClientCode = dbo.mstSaleClientDetails.ClientCode AND
C.AsmtId = dbo.mstSaleClientDetails.AsmtId AND C.LocationAutoId = dbo.mstSaleClientDetails.LocationAutoID
INNER JOIN dbo.mstLocation ON C.LocationAutoId = dbo.mstLocation.LocationAutoID
INNER JOIN @TmpDeployment X on C.SoNo= X.SoNo AND C.SoLineNo=X.SoLineNo
WHERE Dutydate BETWEEN @FROMDATE AND @TODATE AND C.ClientCode NOT LIKE '%INTERNAL%'
GROUP BY C.LocationAutoId, dbo.mstLocation.LocationDesc, dbo.mstSaleClientDetails.AreaID, C.ClientCode, dbo.mstSaleClient.ClientName,M.BillingPattern , C.AsmtID,
dbo.mstSaleClientDetails.AsmtName, C.Dutydate, DatePart(Day,c.DutyDate), C.PostAutoID, C.PostDesc, X.ChargeRatePerHour,x.MonthlyRate
END
ELSE
BEGIN
INSERT INTO @TmpContract
SELECT C.LocationAutoId, dbo.mstLocation.LocationDesc, dbo.mstSaleClientDetails.AreaID, C.ClientCode,dbo.mstSaleClient.ClientName, m.BillingPattern, C.AsmtID,
dbo.mstSaleClientDetails.AsmtName,C.Dutydate, DatePart(Day,c.DutyDate) as DayNbr, C.PostAutoID, C.PostDesc, X.ChargeRatePerHour,x.MonthlyRate,SUM(C.ContractedHrs)
FROM dbo.tblContractHrs C INNER JOIN
dbo.mstSaleClient ON C.ClientCode = dbo.mstSaleClient.ClientCode INNER JOIN
dbo.mstSaleClientDetails ON C.ClientCode = dbo.mstSaleClientDetails.ClientCode AND
C.AsmtId = dbo.mstSaleClientDetails.AsmtId AND C.LocationAutoId = dbo.mstSaleClientDetails.LocationAutoID INNER JOIN
dbo.mstLocation ON C.LocationAutoId = dbo.mstLocation.LocationAutoID
INNER Join @TmpSalesOrder M ON C.ClientCode=M.ClientCode and C.SoNo=M.SoNo
INNER JOIN @TmpDeployment X on C.SoNo= X.SoNo AND C.SoLineNo=X.SoLineNo
WHERE c.LocationAutoId =@LocationAutoId and Dutydate BETWEEN @FROMDATE AND @TODATE AND C.ClientCode NOT LIKE '%INTERNAL%'
GROUP BY C.LocationAutoId, dbo.mstLocation.LocationDesc, dbo.mstSaleClientDetails.AreaID, C.ClientCode, dbo.mstSaleClient.ClientName,M.BillingPattern , C.AsmtID,
dbo.mstSaleClientDetails.AsmtName, C.Dutydate, DatePart(Day,c.DutyDate), C.PostAutoID, C.PostDesc, X.ChargeRatePerHour,x.MonthlyRate
END
--select * from @TmpContract
---------------------------------
-- STEP 2. Extract Actual Hours
---------------------------------
DECLARE @TmpRoster TABLE
(
LocationAutoId int,
ClientCode nvarchar(16),
BillingPattern char(1),
AsmtID udtAssmtID,
DutyDate Date,
PostAutoID Numeric(18,0),
ActualHrs numeric(32,2)
)
IF @LocationAutoId = 0
BEGIN
INSERT INTO @TmpRoster
SELECT LocationAutoID,R.ClientCode,M.BillingPattern,AsmtID,DutyDate,PostAutoID,
Sum((DutyMin + 0.00) / 60 )
FROM dbo.trnRoster R
INNER JOIN @TmpSalesOrder M on R.ClientCode=M.ClientCode and R.SoNo=M.SoNo
WHERE DutyDate BETWEEN @FROMDATE AND @TODATE AND R.ClientCode NOT LIKE '%INTERNAL%'
GROUP by LocationAutoID,R.ClientCode,m.BillingPattern, AsmtID,DutyDate, PostAutoID
END
ELSE
BEGIN
INSERT INTO @TmpRoster
SELECT LocationAutoID,R.ClientCode,M.BillingPattern,AsmtID,DutyDate,PostAutoID,
Sum((DutyMin + 0.00) / 60 )
FROM dbo.trnRoster R
INNER JOIN @TmpSalesOrder M on R.ClientCode=M.ClientCode and R.SoNo=M.SoNo
WHERE DutyDate BETWEEN @FROMDATE AND @TODATE AND R.LocationAutoID=@LocationAutoId AND R.ClientCode NOT LIKE '%INTERNAL%'
GROUP by LocationAutoID,R.ClientCode,m.BillingPattern, AsmtID,DutyDate, PostAutoID
END
--select * from @TmpRoster
----------------------------------------------
-- STEP 3. Merge Actual Hours with Contracted Hours
------------------------------------------------
DECLARE @TmpMergeHours TABLE
(
LocationAutoId int,
LocationDesc nvarchar(50),
AreaID nvarchar(16),
ClientCode nvarchar(16),
ClientName nvarchar(100),
BillingPattern char(1),
AsmtID udtAssmtID,
AsmtName nvarchar(100),
DutyDate Date,
DayNbr int,
PostAutoID Numeric(18,0),
PostDesc nvarchar(200),
ChargeRatePerHour numeric(18,2),
MonthlyRate Money,
BillableHours numeric(18,2)
)
IF @AreaID='*'
BEGIN
INSERT INTO @TmpMergeHours
SELECT C.LocationAutoId,C.LocationDesc, c.AreaID, C.ClientCode, C.ClientName, c.BillingPattern,
C.AsmtID,C.AsmtName,C.DutyDate,c.DayNbr,C.PostAutoID,C.PostDesc,c.ChargeRatePerHour,c.MonthlyRate,
case when c.BillingPattern='F' Then C.ContractedHours else R.ActualHrs end As PayHours
FROM @TmpContract C LEFT OUTER JOIN
@TmpRoster R ON C.LocationAutoId = R.LocationAutoID AND
C.ClientCode = R.ClientCode AND
C.BillingPattern=R.BillingPattern AND
C.AsmtId = R.AsmtID AND
c.DutyDate=r.DutyDate AND
C.PostAutoID =R.PostAutoID
END
ELSE
BEGIN
INSERT INTO @TmpMergeHours
SELECT C.LocationAutoId,C.LocationDesc, c.AreaID, C.ClientCode, C.ClientName, c.BillingPattern,
C.AsmtID,C.AsmtName,C.DutyDate,c.DayNbr,C.PostAutoID,C.PostDesc,c.ChargeRatePerHour,c.MonthlyRate,
case when c.BillingPattern='F' Then C.ContractedHours else R.ActualHrs end As PayHours
FROM @TmpContract C LEFT OUTER JOIN
@TmpRoster R ON C.LocationAutoId = R.LocationAutoID AND
C.ClientCode = R.ClientCode AND
C.BillingPattern=R.BillingPattern AND
C.AsmtId = R.AsmtID AND
c.DutyDate=r.DutyDate AND
C.PostAutoID =R.PostAutoID
where c.ClientCode in(select part from PNG_SplitString(@ClientCode,',')) and
AreaID in(select part from PNG_SplitString(@AreaID,','))
END
--SELECT * FRom @TmpMergeHours
----------------------------------------------
-- STEP 4. Apply Public Holidays Hours
------------------------------------------------
update @TmpMergeHours
set BillableHours=BillableHours*2
where BillingPattern='A' and DutyDate in (select HolidayDate from @TmpTrnHoliday)
---------------------------------
-- STEP 5. Create Pivot table i.e. Format Calender Month
---------------------------------
DECLARE @TmpGuardBreakup TABLE
(
LocationAutoId int,
LocationDesc nvarchar(100),
AreaID nvarchar(16),
ClientCode nvarchar(16),
ClientName nvarchar(100),
AsmtID udtAssmtID,
AsmtName nvarchar(100),
BillingPattern char(1),
PostAutoID Numeric(18,0),
PostDesc nvarchar(200),
ChargeRatePerHour numeric(18,2),
MonthlyRate Money,
D01 int,
D02 int,
D03 int,
D04 int,
D05 int,
D06 int,
D07 int,
D08 int,
D09 int,
D10 int,
D11 int,
D12 int,
D13 int,
D14 int,
D15 int,
D16 int,
D17 int,
D18 int,
D19 int,
D20 int,
D21 int,
D22 int,
D23 int,
D24 int,
D25 int,
D26 int,
D27 int,
D28 int,
D29 int,
D30 int,
D31 int
)
INSERT INTO @TmpGuardBreakup
Select * from
(
SELECT c.LocationAutoId, c.LocationDesc, c.AreaID, c.ClientCode, c.ClientName, c.AsmtID,
c.AsmtName,c.BillingPattern, C.PostAutoID ,C.PostDesc, C.ChargeRatePerHour,C.MonthlyRate,C.BillableHours,DayNbr
FROM @TmpMergeHours c
)
src
PIVOT
(
sum(src.[BillableHours])
FOR src.DayNbr IN ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23],[24],[25],[26],[27],[28],[29],[30],[31])
) AS PivotedView
-- -------------------------------
-- --STEP 5. Perform Calculations for Totals and OUTPUT
-------------------------------------
select T.*,c.IsGSTExempted,
(IsNull(D01,0)+IsNull(D02,0)+IsNull(D03,0)+IsNull(D04,0)+IsNull(D05,0)+IsNull(D06,0)+IsNull(D07,0)+IsNull(D08,0)+IsNull(D09,0)+IsNull(D10,0)+IsNull(D11,0)+IsNull(D12,0)+IsNull(D13,0)+IsNull(D14,0)+IsNull(D15,0)+IsNull(D16,0)+IsNull(D17,0)+IsNull(D18,0)+IsNull(D19,0)+IsNull(D20,0)+IsNull(D21,0)+IsNull(D22,0)+IsNull(D23,0)+IsNull(D24,0)+IsNull(D25,0)+IsNull(D26,0)+IsNull(D27,0)+IsNull(D28,0)+IsNull(D29,0)+IsNull(D30,0)+IsNull(D31,0)) as TotalHours
from @TmpGuardBreakup T
inner join MstClient C on T.ClientCode=C.ClientCode
Marsh Narewec