T-SQL to Oracle query conversion - sql

I have been trying to convert some SQL Server queries that I wrote over into Oracle. I have my original SQL queries up on pastebin here: https://pastebin.com/Ru19FCzG but I am working through it one block at a time.
Here is the block I am working on currently(which is the most important one)
Original Query:
declare #name varchar(max) = 'SPRING 1 2017 RTP';
declare #term varchar(30), #session varchar(1), #loc varchar(2), #id nvarchar(255);
set #term = '17SP1';
set #session='1';
set #loc = 'RT';
set #id = CASE WHEN #session = '2'
then ('%-%-' + #loc + '[5-9]%-' + #term)
else ('%-%-' + #loc + '[0-4]%-'+ #term)
END;
select dr.crsmain_batch_uid [course_id], (us.firstname+' '+us.lastname)[instructor],
q.qtext_body[question], qr.answer_text[answer], ac.points[points]
into #survey_results
from clp_sv_question_response qr
join deployment_response dr on qr.deployment_response_pk1=dr.pk1
join deployment d on dr.deployment_pk1=d.pk1
join clp_sv_answer_choice ac on qr.clp_sv_answer_choice_pk1=ac.pk1
join clp_sv_subquestion sq on ac.clp_sv_subquestion_pk1=sq.pk1
join clp_sv_question q on sq.clp_sv_question_pk1=q.pk1
left join (
select c.batch_uid, u.firstname, u.lastname from course_users cu
join users u on u.pk1=cu.users_pk1
join course_main c on cu.crsmain_pk1=c.pk1
where (c.course_id like #id)
and cu.role='P' and u.user_id not like '%_admin') us on dr.crsmain_batch_uid=us.batch_uid
where d.name=#name
order by dr.crsmain_batch_uid, instructor,
q.qtext_body, qr.answer_text, ac.points;
Here is the Modified query that I have that isn't working yet.
Oracle:
define name = 'SPRING 1 2017 RTP';
define term = '17SP1';
define session = '1';
define loc = 'RT';
define id = IF &session = '1'
then (course_id, '[a-z]{3,}|[0-9]{3}|'loc'[0-4]{1}[0-9]{1}'term,'i')
else (course_id, '[a-z]{3,}|[0-9]{3}|'loc'[5-9]{1}[0-9]{1}'term,'i')
END IF;
create table survey_results as
select dr.crsmain_batch_uid as "course_id", (us.firstname+' '+us.lastname) as "instructor",
q.qtext_body as "question", qr.answer_text as "answer", ac.points as "points"
from clp_sv_question_response as qr
inner join deployment_response as dr on qr.deployment_response_pk1=dr.pk1
inner join deployment as d on dr.deployment_pk1=d.pk1
inner join clp_sv_answer_choice as ac on qr.clp_sv_answer_choice_pk1=ac.pk1
inner join clp_sv_subquestion as sq on ac.clp_sv_subquestion_pk1=sq.pk1
inner join clp_sv_question as q on sq.clp_sv_question_pk1=q.pk1
left join (
select c.batch_uid, u.firstname, u.lastname from course_users as cu
join users as u on u.pk1=cu.users_pk1
join course_main as c on cu.crsmain_pk1=c.pk1
where (c.course_id regexp_like &id)
and cu.role='P' and u.user_id not like '%_admin') as "us" on dr.crsmain_batch_uid=us.batch_uid
where d.name=&name
order by dr.crsmain_batch_uid, instructor,
q.qtext_body, qr.answer_text, ac.points;
Any help at all would be appreciated.

Try using a PL/SQL Block
Declare
name varchar2(20);
term varchar2(10);
session varchar2(1);
loc varchar2(2);
id varchar2(100)
Begin
name = 'SPRING 1 2017 RTP';
term = '17SP1';
session = '1';
loc = 'RT';
SELECT DECODE(session , '1', 'Then value', 'Else Value')
INTO ID
FROm DUAL;
YOUR REST OF THE QUERY
END:

Related

Replacing Is Null Or Exist Inner Query Logic to Reduce Stored Procedure Execution Time

My stored procedure is currently using Is Null Or Exist logic combined with an inner query to filter out the records. The stored procedure is converting multiple comma-separated input values to temp tables (in the production scenario, the input record count will be much higher). And the inner query is using these temp tables for filter conditions. Due to the concern over query execution time would like to change the existing inner-query with an alternate (like left join). But need to retain the same Is Null Or Exist logic. Any suggestions?
DECLARE #SelectedOfferes varchar(1000) = 'FLT10,SPL20'
DECLARE #SelectedBrandCode varchar(1000) = '208,406'
DECLARE #CategoryCode varchar(1000) = 'GMOVN2,CELSMR,LCDTV38IN'
CREATE TABLE #SelectedOfferes
(
DiscountCode VARCHAR(20)
)
CREATE TABLE #BrandCode
(
BrandCode VARCHAR(20)
)
CREATE TABLE #CategoryCode
(
CategoryCode VARCHAR(20)
)
IF #SelectedOfferes IS NOT NULL
BEGIN
INSERT INTO #SelectedOfferes
SELECT part
FROM dbo.[FormatTextByDelimiter] (#SelectedOfferes, ',')
END
IF #SelectedBrandCode IS NOT NULL
BEGIN
INSERT INTO #BrandCode
SELECT part
FROM dbo.[FormatTextByDelimiter] (#SelectedBrandCode, ',')
END
IF #CategoryCode IS NOT NULL
BEGIN
INSERT INTO #CategoryCode
SELECT part
FROM dbo.[FormatTextByDelimiter] (#CategoryCode, ',')
END
SELECT *
FROM Products P
INNER JOIN Discount D ON P.DiscountCode = D.DiscountCode
INNER JOIN AvailableBrand AB ON P.BrandCode = AB.BrandCode
INNER JOIN Category C ON P.CategoryCode = C.CategoryCode
WHERE (#SelectedOfferes IS NULL
OR (EXISTS (SELECT 1 FROM #SelectedOfferes OFR
WHERE OFR.DiscountCode = P.DiscountCode)))
AND (#SelectedBrandCode IS NULL
OR (EXISTS (SELECT 1 FROM #BrandCode BC
WHERE BC.BrandCode = P.BrandCode)))
AND (#CategoryCode IS NULL
OR (EXISTS (SELECT 1 FROM #CategoryCode CAT
WHERE CAT.CategoryCode = P.CategoryCode)))
Dynamic SQL version
I have some questions about your string split function, is it set-based or a looping query? If it's not set-based then you should probably replace it with Jeff Moden's DelimitedSplit8K available at http://www.sqlservercentral.com/articles/Tally+Table/72993/ .
The below example should work the same as what you supplied but should be faster since it removes the ORs and the correlated subqueries from the WHERE clause. I'm not a fan of using dynamic SQL but sometimes it is the best way to get the job done. Maybe someone else can come up with a non-dynamic solution that works as well or better.
DECLARE #SelectedOfferes varchar(1000) = 'FLT10,SPL20'
DECLARE #SelectedBrandCode varchar(1000) = '208,406'
DECLARE #CategoryCode varchar(1000) = 'GMOVN2,CELSMR,LCDTV38IN'
CREATE TABLE #SelectedOfferes
(
DiscountCode VARCHAR(20)
)
CREATE TABLE #BrandCode
(
BrandCode VARCHAR(20)
)
CREATE TABLE #CategoryCode
(
CategoryCode VARCHAR(20)
)
IF #SelectedOfferes IS NOT NULL
BEGIN
INSERT INTO #SelectedOfferes
SELECT part
FROM dbo.[FormatTextByDelimiter] (#SelectedOfferes, ',')
END
IF #SelectedBrandCode IS NOT NULL
BEGIN
INSERT INTO #BrandCode
SELECT part
FROM dbo.[FormatTextByDelimiter] (#SelectedBrandCode, ',')
END
IF #CategoryCode IS NOT NULL
BEGIN
INSERT INTO #CategoryCode
SELECT part
FROM dbo.[FormatTextByDelimiter] (#CategoryCode, ',')
END
DECLARE #SQL NVarchar(4000);
SET #SQL = N'SELECT *
FROM Products P
INNER JOIN Discount D ON P.DiscountCode = D.DiscountCode
INNER JOIN AvailableBrand AB ON P.BrandCode = AB.BrandCode
INNER JOIN Category C ON P.CategoryCode = C.CategoryCode'
IF #SelectedOfferes IS NOT NULL
SET #SQL = #SQL + N'
INNER JOIN #SelectedOfferes OFR ON OFR.DiscountCode = P.DiscountCode';
IF #SelectedBrandCode IS NOT NULL
SET #SQL = #SQL + N'
INNER JOIN #BrandCode BC ON BC.BrandCode = P.BrandCode';
IF #CategoryCode IS NOT NULL
SET #SQL = #SQL + N'
INNER JOIN #CategoryCode CAT ON CAT.CategoryCode = P.CategoryCode';
EXEC sys.sp_executesql #stmt = #SQL;
This method doesn't quite do what the OP wanted but is valid in many other cases
I have some questions about your string split function, is it set-based or a looping query? If it's not set-based then you should probably replace it with Jeff Moden's DelimitedSplit8K available at http://www.sqlservercentral.com/articles/Tally+Table/72993/ .
But either way the below change to your last query should help quite a bit. The IS NULL parts aren't needed since it is a LEFT JOIN and the table will be empty if the variable it is built with is NULL, so you get the same result with less work for the engine.
SELECT *
FROM Products P
INNER JOIN Discount D ON P.DiscountCode = D.DiscountCode
INNER JOIN AvailableBrand AB ON P.BrandCode = AB.BrandCode
INNER JOIN Category C ON P.CategoryCode = C.CategoryCode
LEFT JOIN #SelectedOfferes OFR ON OFR.DiscountCode = P.DiscountCode
LEFT JOIN #BrandCode BC ON BC.BrandCode = P.BrandCode
LEFT JOIN #CategoryCode CAT ON CAT.CategoryCode = P.CategoryCode

Avoid function in where clause,due to that its causing performance issue?

Whenever I'm executing the procedure I got performance issue, where do I need to change the procedure to increase the performance?
I have called table function in where clause I need to optimize this procedure without using string.
CREATE PROC proc_productwise_report #cmp_id VARCHAR(max), #unitcode VARCHAR(max), #gr_code VARCHAR(max), #store_code VARCHAR(max), #from_dt VARCHAR(20), #to_dt VARCHAR(20)
AS
BEGIN
SELECT sh.cmp_id, d.unitcode, d.store_code, st.item_code AS product, d.item_code, im.item_desc, SUM(charge_qty) AS challan_qty
FROM ps_invenstatic sh
INNER JOIN ps_invenstaticdet st ON sh.cmp_id = st.cmp_id
AND sh.sys_no_id = st.sys_no_id
AND sh.doc_id = st.doc_id
AND sys_doc_type = 'PSCH'
INNER JOIN ps_invenissu h ON sh.cmp_id = h.cmp_id
AND sh.doc_type = h.ref_doc_type
AND sh.doc_no = h.ref_doc_no
AND h.prod_code = st.item_code
INNER JOIN ps_invenissudet d ON h.cmp_id = d.cmp_id
AND h.sys_no_id = d.sys_no_id
AND h.doc_id = d.doc_id
INNER JOIN ps_itemmas im ON sh.cmp_id = im.cmp_id
AND im.item_code = d.item_code
WHERE sh.cmp_id IN (
SELECT *
FROM utilfn_split(#cmp_id, ',')
)
AND d.unitcode IN (
SELECT *
FROM utilfn_split(#unitcode, ',')
)
AND im.gr_code IN (
SELECT *
FROM utilfn_split(#gr_code, ',')
)
AND d.store_code IN (
SELECT *
FROM utilfn_split(#store_code, ',')
)
AND h.doc_dt BETWEEN convert(DATETIME, #from_dt, 103)
AND convert(DATETIME, #to_dt, 103)
AND sh.Stat_Code <> 'CA'
GROUP BY sh.cmp_id, d.unitcode, d.store_code, st.item_code, d.item_code, im.item_desc
END
I need to avoid function in where clause and resolve the performance issue.
You can build temporary tables in your stored procedure with the result of the SPLIT and INNER JOIN those temporary tables in your main query.
CREATE PROC proc_productwise_report #cmp_id VARCHAR(max), #unitcode VARCHAR(max),
#gr_code VARCHAR(max), #store_code VARCHAR(max), #from_dt VARCHAR(20), #to_dt VARCHAR(20)
AS
BEGIN
SELECT *
INTO #cmp_ids
FROM utilfn_split(#cmp_id, ',');
SELECT *
INTO #unitcodes
FROM utilfn_split(#unitcode, ',');
SELECT *
INTO #gr_codes
FROM utilfn_split(#gr_code, ',');
SELECT *
INTO #store_codes
FROM utilfn_split(#store_code, ',');
SELECT
sh.cmp_id
, d.unitcode
, d.store_code
, st.item_code AS product
, d.item_code
, im.item_desc
, SUM(charge_qty) AS challan_qty
FROM ps_invenstatic sh
INNER JOIN ps_invenstaticdet st
ON sh.cmp_id = st.cmp_id
AND sh.sys_no_id = st.sys_no_id
AND sh.doc_id = st.doc_id
AND sys_doc_type = 'PSCH'
INNER JOIN ps_invenissu h
ON sh.cmp_id = h.cmp_id
AND sh.doc_type = h.ref_doc_type
AND sh.doc_no = h.ref_doc_no
AND h.prod_code = st.item_code
INNER JOIN ps_invenissudet d
ON h.cmp_id = d.cmp_id
AND h.sys_no_id = d.sys_no_id
AND h.doc_id = d.doc_id
INNER JOIN ps_itemmas im
ON sh.cmp_id = im.cmp_id
AND im.item_code = d.item_code
INNER JOIN #cmp_ids tci on sh.cmp_id = tci.[value]
INNER JOIN #unitcodes tuc on d.unitcode = tuc.[value]
INNER JOIN #gr_codes tgr on im.gr_code = tgr.[value]
INNER JOIN #store_codes tsc on d.store_code = tsc.[value]
WHERE h.doc_dt BETWEEN convert(DATETIME, #from_dt, 103)
AND convert(DATETIME, #to_dt, 103)
AND sh.Stat_Code <> 'CA'
GROUP BY sh.cmp_id
, d.unitcode
, d.store_code
, st.item_code
, d.item_code
, im.item_desc
END
Use table-valued parameters instead of CSV strings. Alternatively in your proc
create temp tables (table variables) first.
declare #tunitcode table (id int); -- you type may be different
insert #tunitcode(id)
select *
from utilfn_split(#unitcode, ',');
.. AND d.unitcode IN (
SELECT * FROM #tunitcode)
..

Convert all rows into different in sql server

I have a stored procedure that is showing a list of doctors and their details based on the sub-department they belong to. Below is the stored proc:
CREATE PROCEDURE SP_BILL_FOOTER_DOCTOR
#subDepartmentId int
AS
BEGIN
SELECT HETC_MST_EMPLOYEE.EMPLOYEE_NAME,
HETC_PAR_EMPLOYEE_TYPE.EMPLOYEE_TYPE_NAME,
HETC_MST_DOCTOR_SPECIALITY.DOCTOR_SPECIALITY_DESCRIPTION,
HETC_MST_SUB_DEPARTMENT.SUB_DEPARTMENT_NAME,
HETC_MST_EMPLOYEE.DOCTOR_SIGNATURE,
CASE WHEN HETC_MST_EMPLOYEE.DOCTOR_SIGNATURE = ''
THEN ''
ELSE ISNULL(SIGNATURE_PATH.DOCUMENT_PATH,'')+ HETC_MST_EMPLOYEE.DOCTOR_SIGNATURE
END AS DOCTOR_SIGNATURE_PIC
FROM HETC_MST_EMPLOYEE
INNER JOIN HETC_PAR_EMPLOYEE_TYPE
ON HETC_PAR_EMPLOYEE_TYPE.EMPLOYEE_TYPE_ID = HETC_MST_EMPLOYEE.EMPLOYEE_TYPE_ID
INNER JOIN HETC_MST_DOCTOR_SPECIALITY
ON HETC_MST_DOCTOR_SPECIALITY.DOCTOR_SPECIALITY_ID = HETC_MST_EMPLOYEE.DOCTOR_SPECIALITY_ID
INNER JOIN HETC_MST_DOCTOR_DEPARTMENT
ON HETC_MST_DOCTOR_DEPARTMENT.EMPLOYEE_ID = HETC_MST_EMPLOYEE.EMPLOYEE_ID
INNER JOIN HETC_MST_SUB_DEPARTMENT
ON HETC_MST_SUB_DEPARTMENT.SUB_DEPARTMENT_ID = HETC_MST_DOCTOR_DEPARTMENT.SUB_DEPARTMENT_ID
LEFT JOIN (SELECT DOCUMENT_PATH
FROM HETC_MST_DOCUMENT_PATH
INNER JOIN HETC_MST_TYPE_OF_ATTACHMENT
ON HETC_MST_DOCUMENT_PATH.TYPE_OF_DOCUMENT_ID = HETC_MST_TYPE_OF_ATTACHMENT.TYPE_OF_DOCUMENT_ID
WHERE HETC_MST_TYPE_OF_ATTACHMENT.TYPE_OF_DOCUMENT_CODE='DSI') AS DOC_SIGNATURE_PIC
ON 1=1
WHERE HETC_MST_SUB_DEPARTMENT.SUB_DEPARTMENT_ID = #subDepartmentId
END
Below is the link of the output that follows when procedure executes :
I want to know is it possible to convert the rows in different column. Like the output has 6 columns and 2 rows, I want all the data in 1 row with 12 columns. Below is the sample output:
It would be of great help if somebody could guide me on how to do it. I have understood that by using Pivot in Sql, I can achieve this, but none I have found to my specific case.
Please have a look at updated code below:
select *, row_number() over(order by employee_name) rownum into #a from (
SELECT HETC_MST_EMPLOYEE.EMPLOYEE_NAME,
HETC_PAR_EMPLOYEE_TYPE.EMPLOYEE_TYPE_NAME,
HETC_MST_DOCTOR_SPECIALITY.DOCTOR_SPECIALITY_DESCRIPTION,
HETC_MST_SUB_DEPARTMENT.SUB_DEPARTMENT_NAME,
HETC_MST_EMPLOYEE.DOCTOR_SIGNATURE,
CASE WHEN HETC_MST_EMPLOYEE.DOCTOR_SIGNATURE = ''
THEN ''
ELSE ISNULL(SIGNATURE_PATH.DOCUMENT_PATH,'')+ HETC_MST_EMPLOYEE.DOCTOR_SIGNATURE
END AS DOCTOR_SIGNATURE_PIC
FROM HETC_MST_EMPLOYEE
INNER JOIN HETC_PAR_EMPLOYEE_TYPE
ON HETC_PAR_EMPLOYEE_TYPE.EMPLOYEE_TYPE_ID = HETC_MST_EMPLOYEE.EMPLOYEE_TYPE_ID
INNER JOIN HETC_MST_DOCTOR_SPECIALITY
ON HETC_MST_DOCTOR_SPECIALITY.DOCTOR_SPECIALITY_ID = HETC_MST_EMPLOYEE.DOCTOR_SPECIALITY_ID
INNER JOIN HETC_MST_DOCTOR_DEPARTMENT
ON HETC_MST_DOCTOR_DEPARTMENT.EMPLOYEE_ID = HETC_MST_EMPLOYEE.EMPLOYEE_ID
INNER JOIN HETC_MST_SUB_DEPARTMENT
ON HETC_MST_SUB_DEPARTMENT.SUB_DEPARTMENT_ID = HETC_MST_DOCTOR_DEPARTMENT.SUB_DEPARTMENT_ID
LEFT JOIN (SELECT DOCUMENT_PATH
FROM HETC_MST_DOCUMENT_PATH
INNER JOIN HETC_MST_TYPE_OF_ATTACHMENT
ON HETC_MST_DOCUMENT_PATH.TYPE_OF_DOCUMENT_ID = HETC_MST_TYPE_OF_ATTACHMENT.TYPE_OF_DOCUMENT_ID
WHERE HETC_MST_TYPE_OF_ATTACHMENT.TYPE_OF_DOCUMENT_CODE='DSI') AS DOC_SIGNATURE_PIC
ON 1=1
WHERE HETC_MST_SUB_DEPARTMENT.SUB_DEPARTMENT_ID = #subDepartmentId )a
declare #iterator int=1
declare #string varchar(max)= ''
declare #string2 varchar(max)= ''
declare #string3 varchar(max)= ''
declare #string4 varchar(max)= ''
declare #exec varchar(max)
while #iterator<=(select max(rownum) from #a)
begin
select #string2=
'['+cast(#iterator as varchar(max))+'].'+ 'EMPLOYEE_NAME'+
',['+cast(#iterator as varchar(max))+'].'+'EMPLOYEE_TYPE_NAME' +
',['+cast(#iterator as varchar(max))+'].'+'DOCTOR_SPECIALITY_DESCRIPTION' +
',['+cast(#iterator as varchar(max))+'].'+'SUB_DEPARTMENT_NAME' +
',['+cast(#iterator as varchar(max))+'].'+'DOCTOR_SIGNATURE'+
',['+cast(#iterator as varchar(max))+'].'+'DOCTOR_SIGNATURE_PIC'
from #a where rownum=#iterator
select #string= #string+#string2
select #string4=
case when #string4='' then
#string4+'['+cast(#iterator as varchar(max))+'].rownum='+cast(#iterator as varchar(max)) else
#string4+' and ['+cast(#iterator as varchar(max))+'].rownum='+cast(#iterator as varchar(max)) end
select #string3= case when #iterator>1 then #string3+' cross join #a ['+ cast(#iterator as varchar(max))+']' else '' end
set #iterator=#iterator+1
end
select #exec = 'select distinct'+ left(#string, len(#string)-1) +' from #a [1] '+#string3+ ' where '+ #string4
exec(''+#exec+'')
This isn't really an answer but a demonstration of how much using aliases can improve the legibility of your queries. Believe it or not this EXACTLY the same thing you posted. I just used aliases so you can read this instead of looking at a wall of text. The only actual change was to use a cross join instead of a left join on 1 = 1.
SELECT e.EMPLOYEE_NAME,
et.EMPLOYEE_TYPE_NAME,
s.DOCTOR_SPECIALITY_DESCRIPTION,
sd.SUB_DEPARTMENT_NAME,
e.DOCTOR_SIGNATURE,
CASE WHEN e.DOCTOR_SIGNATURE = ''
THEN ''
ELSE ISNULL(SIGNATURE_PATH.DOCUMENT_PATH, '') + e.DOCTOR_SIGNATURE
END AS DOCTOR_SIGNATURE_PIC
FROM HETC_MST_EMPLOYEE e
INNER JOIN HETC_PAR_EMPLOYEE_TYPE et ON et.EMPLOYEE_TYPE_ID = e.EMPLOYEE_TYPE_ID
INNER JOIN HETC_MST_DOCTOR_SPECIALITY s ON s.DOCTOR_SPECIALITY_ID = e.DOCTOR_SPECIALITY_ID
INNER JOIN HETC_MST_DOCTOR_DEPARTMENT dd ON dd.EMPLOYEE_ID = e.EMPLOYEE_ID
INNER JOIN HETC_MST_SUB_DEPARTMENT sd ON sd.SUB_DEPARTMENT_ID = dd.SUB_DEPARTMENT_ID
cross join
(
SELECT DOCUMENT_PATH
FROM HETC_MST_DOCUMENT_PATH p
INNER JOIN HETC_MST_TYPE_OF_ATTACHMENT a ON p.TYPE_OF_DOCUMENT_ID = a.TYPE_OF_DOCUMENT_ID
WHERE a.TYPE_OF_DOCUMENT_CODE='DSI'
) AS DOC_SIGNATURE_PIC
WHERE sd.SUB_DEPARTMENT_ID = #subDepartmentId
For the question at hand it is hard to tell what you are really wanting here. Maybe some conditional aggregation in combination with ROW_NUMBER. Or a PIVOT. You would need to post more details for this. Here is a great place to start. http://spaghettidba.com/2015/04/24/how-to-post-a-t-sql-question-on-a-public-forum/

Combining Three Selects into One

I've been trying to consolidate these three SQL functions into one.
Functions
Function 1
`ALTER FUNCTION [dbo].[Fn_Get_User] (#_CompanyKey INT)
RETURNS VARCHAR(8000)
AS
BEGIN
DECLARE #UserIDs AS VARCHAR(8000);
SET #UserIDs = '';
SELECT #UserIDs = #UserIDs + ', ' + x.User_ID
FROM
(SELECT DISTINCT UPPER(p.User_ID) as User_ID
FROM [dbo].[Program] AS p WITH (NOLOCK)
WHERE p.CompanyKey = #_CompanyKey
UNION
SELECT DISTINCT UPPER(ps.User_ID) as User_ID
FROM [dbo].[Program] AS p WITH (NOLOCK)
LEFT OUTER JOIN [dbo].[Program_Scenario] AS ps WITH (NOLOCK)
ON p.ProgramKey = ps.ProgramKey
WHERE p.CompanyKey = #_CompanyKey
AND ps.User_ID IS NOT NULL) x
RETURN Substring(#UserIDs, 3, 8000);
END`
Function 2
`ALTER FUNCTION [dbo].[Fn_Get_Source] (#_CompanyKey INT)
RETURNS VARCHAR(8000)
AS
BEGIN
DECLARE #System_IDs AS VARCHAR(8000);
SET #System_IDs = '';
SELECT #System_IDs = #System_IDs + ', ' + Original_Source_System_ID
FROM (
SELECT DISTINCT p.Original_Source_System_ID
FROM [dbo].[Program] AS p WITH (NOLOCK)
WHERE p.CompanyKey = #_CompanyKey
) a
RETURN Substring(#System_IDs, 3, 8000);
END`
Function 3
`ALTER FUNCTION [dbo].[Fn_Get_ContractNbr] (#_CompanyKey INT)
RETURNS VARCHAR(8000)
AS
BEGIN
DECLARE #ContractNums AS VARCHAR(8000);
SET #ContractNums = '';
SELECT #ContractNums = #ContractNums + ', ' + bi.Contract_Nbr + '-' +
ISNULL(CAST(bi.Year_Nbr AS varchar(8)),'') + '-' +
ISNULL(CAST(bi.Layer_Nbr AS varchar(8)),'')
FROM [dbo].[Program] AS p WITH (NOLOCK)
INNER JOIN [dbo].[Program_Scenario] AS ps WITH (NOLOCK) ON p.ProgramKey = ps.ProgramKey
INNER JOIN [dbo].[Layer] AS l WITH (NOLOCK) ON ps.ProgramScenarioKey = l.ProgramScenarioKey
INNER JOIN [dbo].[Bound_Information] AS bi WITH (NOLOCK) ON l.LayerKey = bi.LayerKey
AND ISNULL(bi.Contract_Nbr,'') <> '' --IS NOT NULL
WHERE p.CompanyKey = #_CompanyKey
RETURN Substring(#ContractNums, 3, 8000);
END`
My attempted Solution
`SET STATISTICS TIME ON
SELECT DISTINCT UPPER((p.User_ID) +', '+ ps.User_ID) as UserID,
bi.Contract_Nbr as ContractNumber,
p.Original_Source_System_ID as SourceSysID,
ISNULL(CAST(bi.Year_Nbr AS varchar(8)),'') as UW_Year,
ISNULL(CAST(bi.Layer_Nbr AS varchar(8)),'') as LayerNumber,
p.CompanyKey,
ps.ProgramKey,
c.Company_Name
FROM
[dbo].[Program] AS p WITH (NOLOCK)
INNER JOIN [dbo].[Program_Scenario] AS ps WITH (NOLOCK)
ON p.ProgramKey = ps.ProgramKey
INNER JOIN [dbo].[Layer] AS l WITH (NOLOCK) ON ps.ProgramScenarioKey = l.ProgramScenarioKey
INNER JOIN [dbo].[Bound_Information] AS bi WITH (NOLOCK) ON l.LayerKey = bi.LayerKey
INNER JOIN [dbo].[Company] AS c with (NOLOCK) ON p.CompanyKey = c.CompanyKey
AND ISNULL(bi.Contract_Nbr,'') <>''
AND ps.User_ID IS NOT NULL
WHERE p.CompanyKey between 2 and 100000
ORDER BY ProgramKey`
My data-set is 20k+ rows so I'm unable to share it here, but where I'm struggling is my function is not returning the same amount of rows as the above three functions. Might there be anything anyone sees to possibly solve this issue? (24755 rows vs. 24052 rows respectively)

Using CSV string Values in 'IN' clause of Dynamic SQL

I have a stored procedure which accepts csv string as the parameter , for eg. ('IN\libin.jose,IN\Pallabi.P'). Stored procedure contains some dynamic sql which make use of this parameter inside IN clause eg : (AND u1.UserName IN (' + #UserNames + ')). Since this is being inside dynamic sql ,The condition is not passing without appending extra single quotes to the CSV values eg ('''IN\libin.jose '' ,''IN\Pallabi.P''')
--exec [GetUwParameterDetails] 'IN\libin.jose,IN\Pallabi.P' , 'false'
ALTER PROCEDURE [dbo].[GetUwParameterDetails]
#UserNames nvarchar(max),
#IncludeInactiveusers bit
AS
BEGIN
declare #selectedUsers nvarchar(max)
--set #selectedUsers = '''IN\libin.jose '' ,''IN\Pallabi.P''';
set #selectedUsers = 'IN\libin.jose,IN\Pallabi.P';
declare #selectedPermissions nvarchar(max)
set #selectedPermissions = '''Underwrite'',''ManageUwTeamPipeline''';
DECLARE #parameterQuery1 AS NVARCHAR(MAX);
set #parameterQuery1 = '
;WITH cte_users
AS (
SELECT users.id
,users.UserName
,users.FirstName
,users.lastname
,users.Email
,users.E3UserName
,UserStatus.[Status]
,Widgets.[Description] DefaultWidget
FROM users
INNER JOIN userparametervalues upv ON users.id = upv.userid
INNER JOIN Parameters p on upv.ParameterId = p.id
AND p.Name = ''UwHierarchy''
INNER JOIN UserPermissions up ON users.id = up.userid
INNER JOIN [Permissions] ps on up.PermissionId = ps.Id
AND ps.IsActive = 1 AND ps.Name IN ('+ #selectedPermissions +')
INNER JOIN users AS u1 ON upv.value = u1.id
AND u1.UserName IN (' + #UserNames + ')
INNER JOIN UserStatus ON users.StatusId = UserStatus.Id
LEFT JOIN Widgets ON users.WidgetId = Widgets.Id )select * from cte_users ';
exec #parameterQuery1
END
How can I achieve this ?
Use this after BEGIN
set #UserNames =''''+replace(#usernames,',',''',''')+''''