How can I had multiple values to a variable or an Array - sql

I have a working query below. however I need to make OWNRSHP_ID a variable that I can supply a list of OWNRSHP_IDs to be ran through the query one by one.
The idea is to have a variable that I can supply a list of ID and the query will run through each one one by one.
This SQL that I'm currently running in Teradata.
Select distinct
inv_corp.OWNRSHP_ID
,SE.Sending_entity_nm AS Bottler
,snap.FSH_DSTR_OWNRSHP_ID AS DELIVERY_SOURCE
,inv_corp.BTLR_DLVR_PNT_NO AS BTLR_DLVR_PNT_NO
,snap.DLVR_PNT_NM AS BTLR_DLVR_PNT_NM
,snap.CHNL_TYPE_DESC AS MARKET_TYPE
,snap.TRADE_CHNL_DESC AS TRADE_CHNL_DESC
,snap.TCCC_SUB_CHNL_NM AS TCCC_SUB_CHNL_NM
,snap.STATE AS STATE
,CASE
WHEN cbs.CBS_BUSINESS_TYPE = 1 THEN 'TRADE SALE'
WHEN cbs.CBS_BUSINESS_TYPE = 4 THEN 'FULL SERVE'
WHEN cbs.CBS_BUSINESS_TYPE = 5 THEN 'EXTRNL SLS'
ELSE NULL
END AS CBS_BUSINESS_TYPE
,ptype.PRD_TYP_NM AS PROD_TYPE
,cal.CUR_YR_AC_PRD AS CAL_YEAR_MONTH
--,cal.CUR_YR_AC_PRD AS CAL_YEAR_MONTH
,inv_corp.Inv_dt
,sum(CASE
WHEN (qty) IS NOT NULL THEN (qty* TCCC_192CONV(FLOAT))
ELSE 0
END )AS VolEQ --20 fields
,sum(CASE
WHEN (qty) IS NOT NULL THEN (cast(qty as FLOAT )* cast(prodet.STD_ADJ_FCT as FLOAT))
ELSE 0
END) AS VolStd
,(sum(Whlsl_Price_Xtnd) - sum(Off_Inv_Cma_Disc)) - (sum(Off_Inv_Ctm_Disc) - sum(On_Inv_Disc) ) as DNSI
FROM CORP_LINES_VIEWS.LINE_CORP line_corp
join corp_invoice_VIEWS.invoice_corp inv_corp
On line_corp.Tsr_Inv_Ref_No = inv_corp.Tsr_Inv_Ref_No
and line_corp.OWNRSHP_ID = inv_corp.OWNRSHP_ID
Join CBS_VIEWS.CBS_DELIVERY_POINT cbs
ON inv_corp.BTLR_DLVR_PNT_NO = cbs.BTLR_DLVR_PNT_NO
and inv_corp.OWNRSHP_ID = cbs.OWNRSHP_ID
Join CHR_VIEWS.DPT_SNAPSHOT_SELECT snap
ON inv_corp.BTLR_DLVR_PNT_NO = snap.BTLR_DLVR_PNT_NO
and inv_corp.OWNRSHP_ID = snap.OWNRSHP_ID
Join CBS_VIEWS.sending_entity se
ON inv_corp.OWNRSHP_ID = se.OWNRSHP_ID
Join NSR_VIEWS.PRODET prodet
ON prodet.cce_material_no = line_corp.cce_material_no
Join DLCCC_CUST_CNTC_CNTR_LAB.TBL_3PY_to_YTD_CAL cal
ON CAL.fact_dt = line_corp.Inv_dt
Join CORP_LINES.MATL_JOIN_KEY mkey
ON mkey.cce_material_no = line_corp.cce_material_no
and mkey.OWNRSHP_ID = line_corp.OWNRSHP_ID
Join IWR_VIEWS.MN_PROD_TYPE ptype
ON ptype.tsr_prd_typ = prodet.tsr_prd_typ
Where 1=1
and line_corp.inv_dt>'2018-01-01'
and line_corp.OWNRSHP_ID IN (10,55,75,110,65,85,95)
GROUP BY
inv_corp.OWNRSHP_ID
,SE.Sending_entity_nm
,snap.FSH_DSTR_OWNRSHP_ID
,inv_corp.BTLR_DLVR_PNT_NO
,snap.DLVR_PNT_NM
,snap.CHNL_TYPE_DESC
,snap.TRADE_CHNL_DESC
,snap.TCCC_SUB_CHNL_NM
,snap.STATE
,cbs.CBS_BUSINESS_TYPE
,ptype.PRD_TYP_NM
,cal.CUR_YR_AC_PRD
,inv_corp.Inv_dt

Well, you currently do supply a list of OWNRSHP_IDs in
and line_corp.OWNRSHP_ID IN (10,55,75,110,65,85,95)
But assuming you want to pass this list as a comma-separated string you can apply STRTOK_SPLI_TO_TABLE
and line_corp.OWNRSHP_ID IN
(
SELECT Cast(token AS INT) AS OWNRSHP_ID, tokennum
FROM TABLE (StrTok_Split_To_Table(1, :OWNRSHP_IDs, ',')
RETURNS (outkey INTEGER,
tokennum INTEGER,
token VARCHAR(20) CHARACTER SET Unicode)
) AS d
)
If you move this into a Derived Table you can even order by the position of the id within the input string:
...
Join IWR_VIEWS.MN_PROD_TYPE ptype
ON ptype.tsr_prd_typ = prodet.tsr_prd_typ
JOIN
(
SELECT Cast(token AS INT) AS OWNRSHP_ID, tokennum
FROM TABLE (StrTok_Split_To_Table(1, :OWNRSHP_IDs, ',')
RETURNS (outkey INTEGER,
tokennum INTEGER,
token VARCHAR(20) CHARACTER SET Unicode)
) AS d
) as dt
ON inv_corp.OWNRSHP_ID = dt.OWNRSHP_ID
...
ORDER BY tokennum;
And when you Outer Join to the Derived Table you can also return a NULL row for a missing ID, but this probably needs some additional changes to your query.

Related

How to use exists for a complete list of a product?

This is the query to find out if a particular car has W1, W2, WA, WH conditions. How can I modify my query so that I can get a list of all the cars as yes or no for these conditions?
NOTE: Here, I have put v.[carnumber] = 't8302' but I need a complete list.
SELECT
CASE
WHEN EXISTS (
SELECT co.[alias]
FROM [MTI_TAXI].[vehicle] v
LEFT JOIN [MTI_SYSTEM].[Conditions] co with (nolock) on v.DispatchSystemID = co.DispatchSystemID and (v.Conditions & co.conditionvalue > 0)
WHERE co.[alias] in ('W1', 'W2', 'WA', 'WH') and v.[DispatchSystemID] = 6 and v.[CarNumber] = 't8302')
THEN cast ('Yes' as varchar)
ELSE cast ('No' as varchar)
END AS [WATS]
OUTPUT - ( WATS - No )
But, here are all the cars but I am getting yes to WATS condition which is incorrect
enter image description here
Simply utilizing your provided filters and moving the EXISTS to be used in an OUTER APPLY statement:
SELECT
CASE
WHEN [find_wats].[Found] = 1
THEN 'Yes'
ELSE 'No'
END AS [WATS]
FROM
[MTI_TAXI].[vehicle] AS v
OUTER APPLY (SELECT TOP (1)
1 AS [Found]
FROM
[MTI_SYSTEM].[Conditions] AS co
WHERE
v.DispatchSystemID = co.DispatchSystemID
AND
(v.Conditions & co.conditionvalue > 0)
AND
co.[alias] IN ('W1', 'W2', 'WA', 'WH')
AND
v.[DispatchSystemID] = 6) AS [find_wats];
Using this set up, you can then use [find_wats].[Found] = 1 to determine that your record within the table [MTI_TAXI].[vehicle] found a match in [MTI_TAXI].[Conditions] (using your provided criteria) while still maintaining a single record in your final result set for each record originally in the table [MTI_TAXI].[vehicle].
Use count(*) to assert that there was exactly 1 row found by adding:
group by co.[alias]
having count(*) = 1
So the whole query becomes:
SELECT
CASE
WHEN EXISTS (
SELECT co.[alias]
FROM [MTI_TAXI].[vehicle] v
LEFT JOIN [MTI_SYSTEM].[Conditions] co with (nolock)
on v.DispatchSystemID = co.DispatchSystemID
and (v.Conditions & co.conditionvalue > 0)
WHERE co.[alias] in ('W1', 'W2', 'WA', 'WH')
and v.[DispatchSystemID] = 6
and v.[CarNumber] = 't8302'
group by co.[alias]
having count(*) = 1
) THEN cast ('Yes' as varchar)
ELSE cast ('No' as varchar)
end AS [WATS]

Why left outer join works like inner join on ABAP CDS view and a custom table?

I have created an ABAP CDS view using ACDOCA, BSID, MARA, MAKT and such tables.
Now my CDS view contains list of customers along with their outstanding (FI) documents.
Against these customers, FI documents and certain more parameters, I am maintaining certain data in a custom table.
Now using left outer join I want to connect this CDS view with custom table.
The problem now is that this join is working like inner join, so if my custom table is blank my output is displaying without values whereas it should be displaying CDS view as it is, and custom table fields as blank.
Now based on similar issues on web I did research and found some useful points:
all conditions on right table are included at most in ON join condition
tried to include null values from right side custom table as well.
tried using just one parameter on join condition to see the result (still working as inner join)
Here is my complete select statement, where:
ZPD1 is my ABAP CDS view of ACDOCA, BSDI ... tables
ZPD_HSL is an ABAP CDS view for customer wise GL amount calculation.
ZFI_PDRATE_MAP is my custom table which contains rate for customer / FI docs combination.
What could be a misstep in this statement?
SELECT
FROM ZPD1( PBUKRS = #BUKRS-LOW ,
POSTFROM = #COL_DATE-LOW ,
POSTTO = #COL_DATE-HIGH ) AS A
LEFT OUTER JOIN ZFI_PDRATE_MAP AS F
ON A~PROD_CATEGORY = F~PROD_CATEGORY
AND A~OD_DATE GE F~POST_DT_FROM
AND A~OD_DATE LE F~POST_DT_TO
AND F~COL_DT_FROM GE #COL_DATE-LOW
AND F~COL_DT_TO LE #COL_DATE-HIGH
AND F~SALES_OFFICE = #VKBUR-LOW
AND CASE WHEN A~ARREAR_DAYS <= 0 THEN 'NOD'
WHEN A~ARREAR_DAYS > 0 THEN 'OD'
END = F~OD
INNER JOIN KNA1 AS H
ON H~KUNNR = A~KUNNR
INNER JOIN TVKBT AS I
ON I~VKBUR = F~SALES_OFFICE
AND I~SPRAS = #SY-LANGU
LEFT OUTER JOIN SKAT AS J
ON J~SAKNR = A~HKONT
AND J~SPRAS = 'E'
AND J~KTOPL = '1000'
LEFT OUTER JOIN MAKT AS K
ON K~MATNR = A~MATNR
AND K~SPRAS = 'E'
LEFT OUTER JOIN T001W AS L
ON L~WERKS = A~WERKS
FIELDS
A~RBUKRS AS BUKRS,
A~KUNNR,
H~NAME1,
F~SALES_OFFICE,
I~BEZEI,
A~BELNR AS COL_BELNR,
A~GJAHR AS COL_GJAHR,
A~HSL AS COL_AMT,
A~BUDAT AS COL_DATE,
A~KEY_DATE AS KEY_OS_DATE,
A~OD_DOC AS OS_BELNR,
A~OD_YR AS OS_GJAHR,
A~BLART ,
A~OD_DATE AS OS_DATE,
CASE WHEN A~SHKZG = 'H' THEN CAST( A~WRBTR * -1 AS CURR( 12, 2 ) )
ELSE A~WRBTR
END AS OS_AMT ,
A~DUE_DATE,
A~ARREAR_DAYS,
CASE WHEN A~ARREAR_DAYS <= 0 THEN 'NOD'
WHEN A~ARREAR_DAYS > 0 THEN 'OD'
ELSE ' '
END AS OD_IND,
A~HKONT,
J~TXT50,
A~PROD_CATEGORY,
A~MATNR,
K~MAKTX,
A~WERKS ,
L~NAME1,
A~BWTAR,
A~PROFIT_CENTRE AS PRCTR,
COALESCE( F~PD_RATE , 0 ) AS RATE,
0 AS PD_AMT,
CASE WHEN A~ARREAR_DAYS > 0 THEN
CAST(
DIVISION(
( CAST( A~WRBTR * F~PD_RATE AS CURR( 15 ,2 ) ) ) ,
100 ,
3 )
AS CURR( 15, 2 ) )
* -1
ELSE
DIVISION(
( CAST( A~WRBTR * F~PD_RATE AS CURR( 15 , 2 ) ) ) ,
100 ,
3 )
END AS ITEM_PD_AMT, "DISCOUNT_RATE,
0 AS ITEM_PD_AMT1,
A~MAIN_TYPE
WHERE A~KUNNR IN #KUNNR
AND NOT EXISTS (
SELECT *
FROM ZFI_PAYMENT_DISC
WHERE BELNR = A~BELNR
AND GJAHR = A~GJAHR
AND BUKRS = A~RBUKRS
AND SALES_OFFICE = #VKBUR-LOW
AND A~KUNNR IN #KUNNR
AND OS_BELNR EQ A~OD_DOC )
AND A~ARREAR_DAYS <= #OD
AND ( F~COL_AMT_FROM LE (
SELECT SUM( COLLECT )
FROM ZPD_HSL( BUKRS = #BUKRS-LOW ,
BUDATFROM = #COL_DATE-LOW ,
BUDATO = #COL_DATE-HIGH )
WHERE KUNNR = A~KUNNR )
AND F~COL_AMT_TO GE (
SELECT SUM( COLLECT )
FROM ZPD_HSL( BUKRS = #BUKRS-LOW ,
BUDATFROM = #COL_DATE-LOW ,
BUDATO = #COL_DATE-HIGH )
WHERE KUNNR = A~KUNNR )
)
ORDER BY A~KUNNR, A~BELNR ,A~DUE_DATE ASCENDING
INTO TABLE #PROV_POST.
This is a mere guess, as your complex setup makes it hard to reproduce a working example.
My assumption is that the INNER JOIN TVKBT AS I ON I~VKBUR = F~SALES_OFFICE is getting in the way. It inner-joins to your custom table, aliased as F, and might lead to an overreduction of records if the join order is interpreted wrong.
I'd recommend to remove that join and see whether that fixes the basic join result.
In any way, I would recommend to add parentheses and reorder the join clauses to make clear what the "left" side of the equation is, and to remove any ambiguity, both for the interpreter, and the reader.

Exclude few selected fields on group by

I had a query that was returning member transaction information. This query has an aggregate function to calculate the amount. All is working fine according to its grouping. Now what I need to do is to add two more columns from different tables. I did try to add them unfortunately they are giving me duplicated information with tons number of records.
Can anyone help me I just want to be able to include the two fields on the query and not include them in the group by clause. And also ensure that data returned is not a duplicate
See below is the query I used.
DECLARE #LastMonthExtractID Int = 11
SELECT x.*
,lstmnth.Submission ---added
,lm_subt.SubmissionTypeDescription ---added
FROM (
SELECT MemberRef --unique key
, SiteName
, ChargePeriod
, SUM(Amount) AS Amount
, TransactionMap
, PackageCode
FROM (
SELECT MemberRef
, SiteName
, ChargePeriod
, Amount
, PackageCode
, CASE WHEN map.TransactionMap = 'JoinFee' AND lstmnth.ChargeDate <> lstmnth.JoinDate THEN 'PayPlan'
WHEN map.TransactionMap = 'MemberFee' AND lstmnth.PackageCode LIKE 'PV%' AND lstmnth.SiteID <> 15 THEN 'VitalityMF' -- must use Package and not CURRENT PACKAGE
WHEN map.TransactionMap = 'MemberFee' AND lstmnth.PackageCode LIKE 'PV%' AND lstmnth.SiteID = 15 THEN 'PlatVitalityMF' -- PLATINUM
WHEN map.TransactionMap = 'MemberFee' AND lstmnth.PackageCode LIKE 'Z%' THEN 'ZContract'
WHEN map.TransactionMap IS NULL THEN 'Other'
ELSE map.TransactionMap END AS TransactionMap
--, lstmnth.Submission
--, lm_subt.SubmissionTypeDescription --added
FROM dbo.CCX_Billing lstmnth
LEFT JOIN dbo.TransactionMap map on lstmnth.TransactionType = map.TransactionType
AND lstmnth.TransactionDescription = map.TransactionDescription
AND ISNULL (lstmnth.AnalysisCode, '') = map.AnalysisCode
WHERE lstmnth.ExtractID = #LastMonthExtractID
) l
GROUP BY SiteName, MemberRef, ChargePeriod, PackageCode, TransactionMap
) x
INNER JOIN dbo.CCX_Billing lstmnth ON lstmnth.MemberRef = x.MemberRef
LEFT JOIN dbo.CCX_Billing_PSubmission lm_sub on lstmnth.SubmissionID = lm_sub.ID
INNER JOIN dbo.CCX_Billing_SubmissionType lm_subt on lm_sub.SubmissionTypeID = lm_subt.SubmissionID --added

multiple errors in using with function in select statement

I'm having some problems with my select statement. When I try to execute it, it gives 3 errors
Must specify table to select from
An object or column name is missing or empty for SELECT INFO statements. verify each column
has a name. For other statements, look for empty alias names. Aliases defined...
Column name or number of supplied values does not match table definition.
WITH A AS
(SELECT ROW_NUMBER() OVER (ORDER BY
CASE
WHEN #pOrderBy = 'SortByName' THEN colPortAgentVendorNameVarchar
WHEN #pOrderBy = 'SortByCOuntry' THEN colCountryNameVarchar
WHEN #pOrderBy = 'SortByCity' THEN colCityNameVarchar
END,
colPortAgentVendorNameVarchar
) xRow, A.*
FROM
(
SELECT DISTINCT
V.colPortAgentVendorIDInt,
colPortAgentVendorNameVarchar = RTRIM(LTRIM(V.colPortAgentVendorNameVarchar)),
C.colCountryNameVarchar,
Y.colCityNameVarchar,
V.colContactNoVarchar,
V.colFaxNoVarchar,
V.colEmailToVarchar,
V.colWebsiteVarchar,
BR.colBrandIdInt,
PR.colPriorityTinyint,
colBrandCodeVarchar = RTRIM(LTRIM(BR.colBrandCodeVarchar))
FROM dbo.TblVendorPortAgent V
LEFT JOIN TblCountry C ON C.colCountryIDInt = V.colCountryIDInt
LEFT JOIN TblCity Y ON Y.colCityIDInt = V.colCityIDInt
LEFT JOIN tblBrandAirportPortAgent PR ON PR.colPortAgentVendorIDInt = V.colPortAgentVendorIDInt
AND PR.colIsActiveBit = 1
LEFT JOIN TblBrand BR ON BR.colBrandIdInt = PR.colBrandIdInt
AND BR.colIsActiveBit = 1
WHERE V.colIsActiveBit = 1
AND V.colPortAgentVendorNameVarchar LIKE '%'+ #pPortAgentVendor +'%'
AND (PR.colBrandIdInt = #pBrandID OR #pBrandID = 0)
) A
)
INSERT INTO #tempPortAgent
SELECT A.*, IsWithContract = CASE WHEN colContractIdInt IS NULL THEN CAST(0 AS BIT) ELSE CAST(1 AS BIT) END FROM A LEFT JOIN TblContractPortAgent B ON A.colPortAgentVendorIDInt = B.colPortAgentVendorIDInt
AND B.colIsActiveBit = 1
;WITH QQ AS
(
SELECT ROW_NUMBER() OVER(PARTITION BY Q.colPortAgentVendorIDInt ORDER BY xRow,
ContractStatusOrder,
colDateCreatedDate DESC
)ContractRow,*
FROM
(
SELECT DISTINCT GG.*, B.colContractIdInt, B.colContractStatusVarchar, B.colDateCreatedDate ,
ContractStatusOrder = CASE WHEN B.colContractStatusVarchar = 'Approved' THEN 1 ELSE '2' END
FROM #tempPortAgent GG LEFT JOIN TblContractPortAgent B ON GG.colPortAgentVendorIDInt = B.colPortAgentVendorIDInt
AND B.colIsActiveBit = 1
) Q
)SELECT * INTO #tempPortAgentWithContract
SELECT * FROM #tempPortAgentWithContract
I don't really know where its showing, because the errors are saying that these are inside the select statements inside.
1- Use Select Into instead of Insert into select
SELECT A.*, IsWithContract = CASE WHEN colContractIdInt IS NULL THEN CAST(0 AS BIT) ELSE CAST(1 AS BIT) END
Into #tempPortAgent
FROM A
LEFT JOIN TblContractPortAgent B ON A.colPortAgentVendorIDInt = B.colPortAgentVendorIDInt
AND B.colIsActiveBit = 1
2- SELECT * INTO #tempPortAgentWithContract is incorrect syntax. you must use following format:
SELECT * INTO #tempPortAgentWithContract From QQ

SQL SP runs Slow

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