I am trying to execute updates while my condition returns results, the problem is that when i am testing the query it never finishes.
Here is the query;
While(select COUNT(*) from Agreement as agr where agr.Id in (
select toa.Id from Agreement_TemporaryOnceAgreement as toa where toa.Executed =1)
and agr.EndingDate is null) > 0
begin
DECLARE #AgreementID int;
SET #AgreementID =
(
select top 1 agr.id from Agreement as agr where agr.Id in (
select toa.Id from Agreement_TemporaryOnceAgreement as toa where toa.Executed =1)
and agr.EndingDate is null
)
update Agreement SET EndingDate = (
select tado.Date from TemporaryAgreementsDateOfExecution tado
where tado.AgreementId = CAST(#AgreementID AS INT))
where Agreement.Id = CAST(#AgreementID AS INT);
end;
You don't need a loop. A single update query resembling this should get the job done.
update a
set EndingDate = tado.date
from Agreement a join TemporaryAgreementsDateOfExecution tado
on a.AgreementId = tado.AgreementId
join Agreement_TemporaryOnceAgreement toa
on a.Id = toa.id
where EndingDate is null
and toa.Executed = 1
There might be slight variations depending on the RDBMS you are using.
Related
When I use a literal in a WHERE clause in a query against a view, the result is basically instantaneous. When I use a variable set to that same value, a completely different and very slow query plan takes its place. How is this possible? How can these be vastly different:
DECLARE #a INT = 5
SELECT ...
WHERE myview.mycol = #a
vs
SELECT ...
WHERE myview.mycol = 5
Here is the exact query and timing that I am encountering (I can post additional information about the view itself, but I don't know that posting the view definition itself is that useful: it is complex and relies on a dozen other views and tables. I can post it if it's helpful in answering the question.)
DECLARE #productdbuid INT = 5
DECLARE #t1 DATETIME;
DECLARE #t2 DATETIME;
---------------------
SET #t1 = GETDATE();
SELECT
*
FROM
vwPublishingActions
WHERE
productdbuid = 5 AND storedbuid = 1
SET #t2 = GETDATE();
SELECT DATEDIFF(MILLISECOND,#t1,#t2) time1;
---------------------
SET #t1 = GETDATE();
SELECT
*
FROM
vwPublishingActions
WHERE
productdbuid = #productdbuid AND storedbuid = 1
SET #t2 = GETDATE();
SELECT DATEDIFF(MILLISECOND,#t1,#t2) time2;
time1: 13
time2: 2796
What is causing SQL Server to treat the literal 5 so differently from #productbuid INT = 5?
Thanks so much for any guidance.
UPDATE: I've been asked to include the view definition:
SELECT
T2.productdbuid,
T2.storedbuid,
ISNULL(paca.publishactiondbuid, 8) publishingaction, -- 8 = ERROR_REPORT
T2.change_product,
T2.change_price,
T2.change_stockstatus,
T2.inventory_belowtrigger,
T2.ruledbuid ruledbuid
FROM
(SELECT
T.productdbuid,
T.storedbuid,
-- pick first fully matching set of conditions
(SELECT TOP 1 paca.dbuid
FROM dbo.z_PublishingActionCalcs paca
WHERE (paca.storetypedbuid = T.storetypedbuid)
AND (paca.publishingcommanddbuid = T.publishcommanddbuid OR paca.publishingcommanddbuid IS NULL)
AND (ISNULL(paca.publishingstatusdbuid, 0) = ISNULL(T.publishstatusdbuid, 1007) OR paca.publishingstatusdbuid IS NULL) -- 1007 = NOTSET
AND (ISNULL(ABS(paca.change_product),0) = ISNULL(ABS(T.change_product),0) OR paca.change_product IS NULL)
AND (ISNULL(ABS(paca.change_price),0) = ISNULL(ABS(T.change_price),0) OR paca.change_price IS NULL)
AND (ISNULL(ABS(paca.change_stockstatus),0) = ISNULL(ABS(T.change_stockstatus),0) OR paca.change_stockstatus IS NULL)
AND (ISNULL(ABS(paca.inventory_belowtrigger),0) = ISNULL(ABS(T.inventory_belowtrigger),0) OR paca.inventory_belowtrigger IS NULL)
AND (ISNULL(paca.stockstatusdbuid, 0) = ISNULL(T.stockstatusdbuid, 0) OR paca.stockstatusdbuid IS NULL)
ORDER BY paca.sort) ruledbuid,
ABS(ISNULL(T.change_product,0)) change_product,
ABS(ISNULL(T.change_price,0)) change_price,
ABS(ISNULL(T.change_stockstatus,0)) change_stockstatus,
ABS(ISNULL(T.inventory_belowtrigger,0)) inventory_belowtrigger
FROM
(SELECT
p.productid,
s.storetypedbuid,
CASE
WHEN pdpcm.publishcommanddbuid <> 4
THEN NULL -- STOCKSTATUS
ELSE pss.stockstatusdbuid
END product_stockstatus,
CASE
WHEN pdpcm.publishcommanddbuid <> 5
THEN NULL -- INVENTORY
ELSE itr.inventory_belowtrigger
END inventory_belowtrigger,
p.dbuid productdbuid,
s.dbuid storedbuid,
pdpc.change_product,
pdpc.change_price,
pdpc.change_stockstatus,
pdpcm.publishcommanddbuid,
pdps.publishstatusdbuid,
pss.stockstatusdbuid
FROM
dbo.ProductDetailsPublishingCommands pdpcm
INNER JOIN
dbo.Stores s ON s.dbuid = pdpcm.storedbuid
INNER JOIN
dbo.Products p ON pdpcm.productdbuid = p.dbuid
INNER JOIN
dbo.StoreTypeSet st ON st.dbuid = s.storetypedbuid
LEFT JOIN
dbo.vwPublishingChanges pdpc ON pdpc.productdbuid = p.dbuid
AND pdpc.storedbuid = s.dbuid
LEFT JOIN
dbo.ProductDetailsPublishingStatuses pdps ON pdps.productdbuid = p.dbuid
AND pdps.storedbuid = s.dbuid
LEFT JOIN
dbo.vwProductStockStatus pss ON pss.productdbuid = p.dbuid
LEFT JOIN
dbo.vwProductInventory pri ON pri.productdbuid = p.dbuid
LEFT JOIN
dbo.vwInventoryTriggers itr ON itr.storedbuid = s.dbuid
AND itr.productdbuid = p.dbuid) T
) T2
LEFT JOIN
dbo.z_PublishingActionCalcs paca ON T2.ruledbuid = paca.dbuid
You would need to look at the execution plan to be sure.
When you use a variable mycol = #a SQL Server will create a plan based on average column density for values in mycol.
The mycol = 5 predicate may be significantly above or below the average. When you use a literal SQL Server can lookup the value 5 in the column statistics and potentially get more accurate estimates and thus a more appropriate plan.
Additionally using a literal can allow some additional optimisations and simplifications.
An example is that a view with a PARTITION BY mycol can have the literal predicate pushed further down than a variable or parameter generally can (except when using OPTION (RECOMPILE)).
Additionally with the literal value available at compilation SQL Server may be able to simplify expressions and use contradiction detection to eliminate some of the work at run time.
Having trouble understanding why my query is taking so long, looking for advice to optimise please.
update Laserbeak_Main.dbo.ACCOUNT_MPN set
DateUpgrade = ord.ConnectedDate
FROM [ORDER] ord
WHERE ord.AccountNumber = Laserbeak_Main.dbo.ACCOUNT_MPN.AccountNumber
AND ord.ordertypeID = '2'
AND ord.ConnectedDate IS NOT NULL
AND DateUpgrade <> ord.ConnectedDate
Execution plan as requested on brentozar.com
UPDATE: Following suggestions the new query looks like this & seems to work much more quickly. However if you run the query it sets the rows as expected, then run again it updates the exact same number of rows. Converting to a select confirms that the same rows are being updated each time. The <> clause should stop this but it doesn't. I believed it was something to do with collation but have been unable to confirm if its possible to have different collations at table level in the same database.
;WITH cteOrderInfo AS (
SELECT DISTINCT ord.AccountNumber, ord.ConnectedDate
FROM [ORDER] ord
WHERE ord.ordertypeID = '2'
AND ord.ConnectedDate IS NOT NULL
)
UPDATE Laserbeak_Main.dbo.ACCOUNT_MPN
SET Laserbeak_Main.dbo.ACCOUNT_MPN.DateUpgrade = cteOrderInfo.ConnectedDate
FROM cteOrderInfo
INNER JOIN Laserbeak_Main.dbo.ACCOUNT_MPN acc
ON cteOrderInfo.AccountNumber = acc.AccountNumber
WHERE cteOrderInfo.ConnectedDate <> acc.DateUpgrade
The SELECT to confirm:
;WITH cteOrderInfo AS (
SELECT DISTINCT ord.AccountNumber, ord.ConnectedDate
FROM [ORDER] ord
WHERE ord.ordertypeID = '2'
AND ord.ConnectedDate IS NOT NULL
)
SELECT cteOrderInfo.ConnectedDate, acc.DateUpgrade
FROM cteOrderInfo
INNER JOIN Laserbeak_Main.dbo.ACCOUNT_MPN acc
ON cteOrderInfo.AccountNumber = acc.AccountNumber
WHERE cteOrderInfo.ConnectedDate <> acc.DateUpgrade
SELECT Results Sample:
As Serge suggested, we did not have unique rows.
the solution we arrived at:
;WITH cteSourceStuff AS (
SELECT AccountNumber, MpnUpgrade, MAX(DateConnected) maxConnDate
FROM ORDER_DETAIL, [ORDER]
WHERE ORDER_DETAIL.OrderID = [ORDER].OrderID
AND LEN(MpnUpgrade) > 10
AND OrderTypeID = 2
GROUP BY AccountNumber, MpnUpgrade
)
UPDATE Laserbeak_Main.dbo.ACCOUNT_MPN set
DateUpgrade = cteSourceStuff.maxConnDate
FROM cteSourceStuff
WHERE cteSourceStuff.MpnUpgrade = ACCOUNT_MPN.Mpn
AND cteSourceStuff.AccountNumber = ACCOUNT_MPN.AccountNumber
AND DateUpgrade <> cteSourceStuff.maxConnDate
This works because the duplicates are initially removed, then we only update the rows that we are actually targeting. The reason we have issues before was that SQL was updating the 1st row it found, then when we re-ran or ran the select it was return rows matched on the key but that had not previously been updated.
I have a procedure that has following functions in where condition:
select col1,col2,col3...
from table1
where
(dbo.GetFilStatus(et.SgDate,et.Speed,(SELECT COUNT(J.JId) FROM tbl_Nt J
inner JOIN tbl_NAssign JN ON JN.NNo =J.NNo
inner JOIN dbo.tbl_CStatus JS ON JS.CStatusID=J.CStatusID
INNER JOIN dbo.tbl_SStatus ss ON ss.SStatusID=JS.SStatusID
WHERE JN.DriID=et.DriID AND ss.SStatusID !=9),et.IgStatus)
in (Select val from Split('A,B,C,D,E',',')))
)
getfilstatus status contains the following code:-
if (#ServerDatetime <= DATEADD(MI,-10, GETDATE()))
BEGIN
IF(#xIgStatus = 'ON')
BEGIN
set #FilStatus= 'NoSignal'
END
ELSE
BEGIN
set #FilStatus= 'Stopped'
end
End
else IF(#xIgStatus = 'ON')
Begin
if(#Speed>5)
begin
if(#JCount<=0)
set #FilStatus='Moving'
else
set #FilStatus='Working'
end
else
begin
set #FilStatus= 'Idle'
end
End
else
Begin
set #FilStatus= 'Stopped'
end
RETURN #FilStatus
GetFilStatus always returns more than 10000 records. Sometimes its more than 100000. Its slowing the final output of query. Currently its taking more than 2 mins to return the output.
I am searching for any other option or any other trick using which the query performance can be increased and I could get the output in seconds.
Any suggestions? Any ideas?
It is better to put the split items in a temp table, as the split function needs to execute each time in the query iterations.
The third parameter has a complex inline query, i have created a temp table for the subset data and filtered necessary data inline.
SELECT S.items AS value
INTO #splited_items
FROM Split('A,B,C,D,E', ',') S;
SELECT Count(J.jid) AS Count_JId,
JN.driid AS DriID
INTO #joined_table
FROM tbl_nt J
INNER JOIN tbl_nassign JN
ON JN.nno = J.nno
INNER JOIN dbo.tbl_cstatus JS
ON JS.cstatusid = J.cstatusid
INNER JOIN dbo.tbl_sstatus ss
ON ss.sstatusid = JS.sstatusid
WHERE ss.sstatusid != 9
GROUP BY JN.driid
SELECT col1,
col2,
col3... from table1
WHERE ( dbo.Getfilstatus(et.sgdate, et.speed, (SELECT count_jid
FROM #joined_table
WHERE driid = et.driid),
et.igstatus)
IN (SELECT value
FROM #splited_items) )
I am trying to write a stored procedure that will give a count of all the cases in a table that are not deleted, grouped by a CaseStatusID in another table, but only the cases that have a CaseStatusID that also isn't deleted. I also want it to return any CaseStatusID that does not have case related to it (i.e. a count of 0)
So far I have tried
Create Table #tCaseStatus (CaseStatusID int,CaseStatusDesc varchar(200) )
declare #NofCases int
declare #CaseStatusID int
declare #CaseStatusDesc varchar(200)
BEGIN
INSERT #tCaseStatus
Select CaseStatusID, CaseStatusDesc From dbo.CaseStatus Where IsDeleted = 0
Select #NofCases = Count(*) From #tCaseStatus
While (#NofCases > 0)
Begin
Select Top (1) #CaseStatusID = CaseStatusID, #CaseStatusDesc = CaseStatusDesc from #tCaseStatus
SELECT CaseStatusDesc, Count(CaseID) AS CountCases
FROM Cases inner join #tCaseStatus on Cases.CaseStatusID = #tCaseStatus.CaseStatusID
WHERE (IsDeleted = 0) AND Cases.CaseStatusID = #CaseStatusID
Group by #tCaseStatus.CaseStatusDesc
Set #NofCases = #NofCases - 1
Delete Top(1) from #tCaseStatus
End
END
AND
This returns the correct cases but excludes any of the CaseStatusDesc that have a count of 0
SELECT CaseStatus.CaseStatusDesc, COUNT(Cases.CaseID) AS CaseCount
FROM Cases FULL OUTER JOIN
CaseStatus ON Cases.CaseStatusID = CaseStatus.CaseStatusID
WHERE (CaseStatus.IsDeleted = 0) AND
(Cases.IsDeleted = 0)
GROUP BY CaseStatus.CaseStatusDesc, CaseStatus.CaseStatusID
ORDER BY CaseStatus.CaseStatusID
AND
this returns all the CaseStatusDesc's even the ones that are deleted
SELECT CaseStatus.CaseStatusDesc, COUNT(CASE
WHEN CaseStatus.IsDeleted = 0 THEN 'ok'
WHEN Cases.IsDeleted = 0 THEN 'ok'
Else null
END) AS [Case]
FROM Cases FULL OUTER JOIN CaseStatus ON Cases.CaseStatusID = CaseStatus.CaseStatusID
GROUP BY CaseStatus.CaseStatusDesc, CaseStatus.CaseStatusID
Order By CaseStatus.CaseStatusID asc
But I cant seem to get the desired results
Is this what you're after?
select
casestatus.casestatusid,
casestatusdesc,
COUNT(caseid)
from casestatus
left join cases
on casestatus.casestatusid = cases.casestatusid
and cases.isdeleted=0
where
casestatus.isdeleted=0
group by
casestatus.casestatusid,
casestatusdesc
Hi
I am using an SP which takes 7 minutes in a server which has 7336 recrds
and 6seconds in another server which has 3500 records.
Can anybody help me to know why is it happening?
Thanks,
-Divya
THE SP:
SELECT WORKSHEET_ID
FROM PERSON PER
INNER JOIN PERSON EMPLEE
ON EMPLEE.PERSON_ID = PER.PERSON_ID
AND
dbo.FN_CHECKRPTSECURITY(EMPLEE.PERSON_ID, #p_SEC_ACCOUNT_ID) > 0
LEFT JOIN SEARCH_ASSIGNMENT_VW PERSON_ASGN
ON PERSON_ASGN.ASSIGNMENT_ID =
dbo.FN_GETRPTASSIGNMENTID(EMPLEE.PERSON_ID)
LEFT JOIN LOOKUP EMPLEE_ASGN_STAT
ON EMPLEE_ASGN_STAT.TYPE_ = 'ASSIGNMMENT_STATUS_CODE'
AND EMPLEE_ASGN_STAT.CODE = PERSON_ASGN.ASGN_STAT_CODE
INNER JOIN
(SELECT w1.ASSIGNMENT_ID, w1.WORKSHEET_ID, w1.EFFECTIVE_DATE, w1.APPROVED_BY, w3.CREATED_BY
FROM WORKSHEET_PAYROLL_VW w1
INNER JOIN WORKSHEET w3
ON w3.WORKSHEET_ID = w1.WORKSHEET_ID
WHERE w1.EFFECTIVE_DATE = CASE
WHEN #p_MOST_RECENT_ONLY = 'Y'
THEN (SELECT MAX(w2.EFFECTIVE_DATE)
FROM WORKSHEET_PAYROLL_VW w2
WHERE w1.ASSIGNMENT_ID = w2.ASSIGNMENT_ID
AND (ISNULL(#p_WKS_EFFECTIVE_DATE,w2.EFFECTIVE_DATE) =w2.EFFECTIVE_DATE))
ELSE ISNULL(#p_WKS_EFFECTIVE_DATE,w1.EFFECTIVE_DATE)
END
)
PERSON_WKS
ON PERSON_WKS.ASSIGNMENT_ID = dbo.FN_GETRPTASSIGNMENTID(EMPLEE.PERSON_ID)
INNER JOIN
(SELECT ASSIGNMENT_ID, VALUE
FROM ASSIGNMENT_HISTORY AH
WHERE FIELD_NAME ='HOME PAYROLL GROUP'
AND EFFECTIVE_DATE = (SELECT MAX(EFFECTIVE_DATE)
FROM ASSIGNMENT_HISTORY
WHERE ASSIGNMENT_ID = AH.ASSIGNMENT_ID
AND EFFECTIVE_DATE <=getDate()
AND FIELD_NAME = 'HOME PAYROLL GROUP')
)HOME_PAYROLL
ON HOME_PAYROLL.ASSIGNMENT_ID = dbo.FN_GETRPTASSIGNMENTID(EMPLEE.PERSON_ID)
WHERE
(#p_SELECTED_PERSON_ONLY = 'N' OR EMPLEE.PERSON_ID = #p_PERSON_ID)
AND
(#p_ASGN_STAT_CODE IS NULL OR PERSON_ASGN.ASGN_STAT_CODE = SUBSTRING(#p_ASGN_STAT_CODE,1,1)
OR PERSON_ASGN.ASGN_STAT_CODE = SUBSTRING(#p_ASGN_STAT_CODE,2,1))
AND
(#p_POLICY_ID IS NULL OR PERSON_ASGN.PROGRAM_CODE = #p_POLICY_ID)
AND
(#p_HOME_COUNTRY_ID IS NULL OR PERSON_ASGN.HOMECOUNTRYID=#p_HOME_COUNTRY_ID)
AND
(#p_HOME_CITY_ID IS NULL OR PERSON_ASGN.HOMECITYID=#p_HOME_CITY_ID )
AND
(#p_HOME_COMPANY_ID IS NULL OR PERSON_ASGN.HOMEBUSINESSID=#p_HOME_COMPANY_ID )
AND
(#p_HOME_DIVISION_ID IS NULL OR PERSON_ASGN.HOMECOMPONENTID=#p_HOME_DIVISION_ID )
AND
(#p_HOST_COUNTRY_ID IS NULL OR PERSON_ASGN.HOSTCOUNTRYID=#p_HOST_COUNTRY_ID )
AND
(#p_HOST_CITY_ID IS NULL OR PERSON_ASGN.HOSTCITYID=#p_HOST_CITY_ID )
AND
(#p_HOST_COMPANY_ID IS NULL OR PERSON_ASGN.HOSTBUSINESSID=#p_HOST_COMPANY_ID )
AND
(#p_HOST_DIVISION_ID IS NULL OR PERSON_ASGN.HOSTCOMPONENTID=#p_HOST_DIVISION_ID )
AND
(#p_CREATED_BY IS NULL OR PERSON_WKS.CREATED_BY=#p_CREATED_BY )
AND
(#p_APPROVED_BY IS NULL OR PERSON_WKS.APPROVED_BY=#p_APPROVED_BY )
AND
(#p_payroll_code IS NULL OR HOME_PAYROLL.VALUE=#p_payroll_code )
ORDER BY PER.LAST_NAME ASC,
PER.FIRST_NAME ASC,
PERSON_WKS.EFFECTIVE_DATE DESC
The Function in the 5th line is the one which is running slow. rest of the part is running in 4secs
The FUNCTION:
BEGIN
DECLARE
#v_ASGN_COUNT INT,
#v_RESULT INT
SELECT #v_ASGN_COUNT = COUNT(ASSIGNMENT_ID) --to find out if this employee has any assignment
FROM ASSIGNMENT
WHERE EXPATRIATE_PERSON_ID = #p_PERSON_ID AND
ASGN_STAT_CODE IN ('PD','A','I')
IF(#v_ASGN_COUNT > 0) --yes assignment, check against SECURITY_ASSIGNMENT_VW
BEGIN
SELECT #v_RESULT = COUNT(ASSIGNMENT_ID)
FROM SECURITY_ASSIGNMENT_VW
WHERE SEC_ACCOUNT_ID = #p_SEC_ACCOUNT_ID AND
ASSIGNMENT_ID IN (SELECT ASSIGNMENT_ID
FROM ASSIGNMENT
WHERE EXPATRIATE_PERSON_ID = #p_PERSON_ID AND
ASGN_STAT_CODE IN ('PD','A','I'))
END
ELSE --no assignment, so check against SECURITY_PERSON_VW
BEGIN
SELECT #v_RESULT = COUNT(PERSON_ID)
FROM SECURITY_PERSON_VW
WHERE SEC_ACCOUNT_ID = #p_SEC_ACCOUNT_ID AND
PERSON_ID = #p_PERSON_ID
END
RETURN #v_RESULT
END
Do the schemas match exactly... in particular check for missing indexes.
Well to begin with you have scalar functions which will run significantly slower as the number of records increase becasue they process row-by-agonizing-row. Not only that you've used the functions in joins which is a horrible practice if you need performance. You have a bunch of OR conditions which tend to slowness. And while it is too hard to actually read the code you posted (please try to format and only use all caps for keywords), I would suspect that some of those conditions are not sargable.
To know what is actually happening check the Execution plan (SQL Server) or Explain Plan (mySQL and others I think) or the equivalent feature in your database. Likely you wil find table scans which of course are going to get significantly slower as the number of records increases.
You may also have a problem with parameter sniffing. Please google to see how to fix that.
One improvement would be to make sure that dbo.FN_GETRPTSSIGNMENTID only gets executed once.
Currently, it gets executed three times.
You can replace two of those calls by joining to the field of the (one) remaing call.
Something like
SELECT WORKSHEET_ID
FROM PERSON PER
INNER JOIN PERSON EMPLEE ON EMPLEE.PERSON_ID = PER.PERSON_ID AND dbo.FN_CHECKRPTSECURITY(EMPLEE.PERSON_ID, #p_SEC_ACCOUNT_ID) > 0
INNER JOIN (
SELECT w1.ASSIGNMENT_ID
, w1.WORKSHEET_ID
, w1.EFFECTIVE_DATE
, w1.APPROVED_BY
, w3.CREATED_BY
FROM WORKSHEET_PAYROLL_VW w1
INNER JOIN WORKSHEET w3 ON w3.WORKSHEET_ID = w1.WORKSHEET_ID
WHERE w1.EFFECTIVE_DATE =
CASE WHEN #p_MOST_RECENT_ONLY = 'Y'
THEN (
SELECT MAX(w2.EFFECTIVE_DATE)
FROM WORKSHEET_PAYROLL_VW w2
WHERE w1.ASSIGNMENT_ID = w2.ASSIGNMENT_ID AND (ISNULL(#p_WKS_EFFECTIVE_DATE,w2.EFFECTIVE_DATE) = w2.EFFECTIVE_DATE)
)
ELSE ISNULL(#p_WKS_EFFECTIVE_DATE,w1.EFFECTIVE_DATE)
END
) PERSON_WKS ON PERSON_WKS.ASSIGNMENT_ID = dbo.FN_GETRPTASSIGNMENTID(EMPLEE.PERSON_ID)
INNER JOIN (
SELECT ASSIGNMENT_ID
, VALUE
FROM ASSIGNMENT_HISTORY AH
WHERE FIELD_NAME ='HOME PAYROLL GROUP'
AND EFFECTIVE_DATE = (
SELECT MAX(EFFECTIVE_DATE)
FROM ASSIGNMENT_HISTORY
WHERE ASSIGNMENT_ID = AH.ASSIGNMENT_ID
AND EFFECTIVE_DATE <=getDate()
AND FIELD_NAME = 'HOME PAYROLL GROUP'
)
LEFT JOIN SEARCH_ASSIGNMENT_VW PERSON_ASGN ON PERSON_ASGN.ASSIGNMENT_ID = PERSON_WKS.ASSIGNMENT_ID
LEFT JOIN LOOKUP EMPLEE_ASGN_STAT ON EMPLEE_ASGN_STAT.TYPE_ = 'ASSIGNMMENT_STATUS_CODE' AND EMPLEE_ASGN_STAT.CODE = PERSON_ASGN.ASGN_STAT_CODE
) HOME_PAYROLL ON HOME_PAYROLL.ASSIGNMENT_ID = PERSON_WKS.ASSIGNMENT_ID
WHERE (#p_SELECTED_PERSON_ONLY = 'N' OR EMPLEE.PERSON_ID = #p_PERSON_ID)
AND (#p_ASGN_STAT_CODE IS NULL OR PERSON_ASGN.ASGN_STAT_CODE = SUBSTRING(#p_ASGN_STAT_CODE,1,1) OR PERSON_ASGN.ASGN_STAT_CODE = SUBSTRING(#p_ASGN_STAT_CODE,2,1))
AND (#p_POLICY_ID IS NULL OR PERSON_ASGN.PROGRAM_CODE = #p_POLICY_ID)
AND (#p_HOME_COUNTRY_ID IS NULL OR PERSON_ASGN.HOMECOUNTRYID=#p_HOME_COUNTRY_ID)
AND (#p_HOME_CITY_ID IS NULL OR PERSON_ASGN.HOMECITYID=#p_HOME_CITY_ID )
AND (#p_HOME_COMPANY_ID IS NULL OR PERSON_ASGN.HOMEBUSINESSID=#p_HOME_COMPANY_ID )
AND (#p_HOME_DIVISION_ID IS NULL OR PERSON_ASGN.HOMECOMPONENTID=#p_HOME_DIVISION_ID )
AND (#p_HOST_COUNTRY_ID IS NULL OR PERSON_ASGN.HOSTCOUNTRYID=#p_HOST_COUNTRY_ID )
AND (#p_HOST_CITY_ID IS NULL OR PERSON_ASGN.HOSTCITYID=#p_HOST_CITY_ID )
AND (#p_HOST_COMPANY_ID IS NULL OR PERSON_ASGN.HOSTBUSINESSID=#p_HOST_COMPANY_ID )
AND (#p_HOST_DIVISION_ID IS NULL OR PERSON_ASGN.HOSTCOMPONENTID=#p_HOST_DIVISION_ID )
AND (#p_CREATED_BY IS NULL OR PERSON_WKS.CREATED_BY=#p_CREATED_BY )
AND (#p_APPROVED_BY IS NULL OR PERSON_WKS.APPROVED_BY=#p_APPROVED_BY )
AND (#p_payroll_code IS NULL OR HOME_PAYROLL.VALUE=#p_payroll_code )
ORDER BY
PER.LAST_NAME ASC
, PER.FIRST_NAME ASC
, PERSON_WKS.EFFECTIVE_DATE DESC