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)
Related
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)
..
I write this query in SQL Server 2016:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[s2_GetReceivedDocumentsCount]
#_Username NVARCHAR(MAX),
#_SearchText NVARCHAR(MAX),
#_States NVARCHAR(MAX),
#_Senders NVARCHAR(MAX),
#_Date1 NVARCHAR(MAX),
#_Date2 NVARCHAR(MAX),
#_Filter1ID NVARCHAR(MAX),
#_Filter1Value NVARCHAR(MAX)
AS
BEGIN
--https://blogs.technet.microsoft.com/mdegre/2011/11/06/what-is-parameter-sniffing/
DECLARE #Username NVARCHAR(MAX)
DECLARE #Fild BIT
DECLARE #SearchText NVARCHAR(MAX)
DECLARE #States NVARCHAR(MAX)
DECLARE #Senders NVARCHAR(MAX)
DECLARE #Date1 NVARCHAR(MAX)
DECLARE #Date2 NVARCHAR(MAX)
DECLARE #Filter1ID NVARCHAR(MAX)
DECLARE #Filter1Value NVARCHAR(MAX)
SELECT
#Username = #_Username,
#SearchText = #_SearchText,
#States = #_States,
#Senders = #_Senders,
#Date1 = #_Date1,
#Date2 = #_Date2,
#Filter1ID = #_Filter1ID,
#Filter1Value = #_Filter1Value
SELECT #SearchText = LTRIM(RTRIM(IsNull(#SearchText, '')))
SELECT #Filter1ID = LTRIM(RTRIM(IsNull(#Filter1ID, '')))
SELECT #Filter1Value = LTRIM(RTRIM(IsNull(#Filter1Value, '')))
DECLARE #PersonalPostID INT = NULL
SELECT #PersonalPostID = p.PostID
FROM Person pr
JOIN PersonPost pp ON pp.PersonID = pr.PersonID
JOIN Post p ON p.PostID = pp.PostID
WHERE pr.Username = #Username
AND p.IsPersonalPost = 1
DECLARE #independentPostExists BIT = CASE
WHEN EXISTS (SELECT 1 FROM Post t
WHERE t.Independent = 1 AND t.PostID > 0)
THEN 1
ELSE 0
END
DECLARE #temp0 TABLE (
DocumentID int
, Likeness int
, ParentScrutinyID int
)
;With AllPost
As
(
Select pp.PostID
From
PersonPost pp
Join Person prs On prs.PersonID = pp.PersonID
Where prs.Username = #Username
Union
Select [type].PostID
From
Post [type]
Join Post p On p.TypeID = [type].PostID
Join PersonPost pp On pp.PostID = p.PostID
Join Person prs On prs.PersonID = pp.PersonID
Where prs.Username = #Username
)
,
SplitSearchText
AS
(
Select * From dbo._1001_Split(dbo.ReplaceYK(#SearchText),N'')
),
Temp0
AS
(
Select Distinct
s.DocumentID
, s.Code
, s2_Scrutiny.ParentScrutinyID
From
s2_Document s
Join s2_State state On state.StateID = s.StateID
Join Post sender On sender.PostID = s.SenderID
Join s2_Scrutiny On
s2_Scrutiny.DocumentID = s.DocumentID
And s2_Scrutiny.IsActive = 1
And s2_Scrutiny.ReferenceID not in (-10, -20)
Cross Join AllPost
Join s2_Producer On s2_Producer.DocumentID = s.DocumentID
Join PersonPost producerPost On producerPost.PostID = s2_Producer.PostID
Join Person producerPerson On producerPerson.PersonID = producerPost.PersonID
Where
1 = 1
And (#States = '' Or (N',' + #States + N',') Like (N'%,' + Cast(s.StateID as nvarchar(max)) + ',%'))
And (#Senders = '' Or (N',' + #Senders + N',') Like (N'%,' + Cast(s.SenderID as nvarchar(max)) + ',%'))
And (#Date1 = '' Or s.RegistrationDate >= #Date1)
And (#Date2 = '' Or s.RegistrationDate <= #Date2)
And (#Filter1ID = ''
Or Exists(
Select 1
From
s2_FieldValue fv
Join s2_Field f On f.FieldID = fv.FieldID
Where
fv.DocumentID = s.DocumentID
And fv.FieldID = #Filter1ID
And (
(f.FieldTypeID in (0, 5/*فیلد محاسباتی*/) And fv.[Value] = #Filter1Value)
Or (f.FieldTypeID = 3 And Cast(fv.[FieldOptionID] as nvarchar(max)) = #Filter1Value)
Or (f.FieldTypeID in(1,2,4))
)
))
--پیشنهاد به پست یا نوع پستی که این شخص حائز آن است، ارجاع شده است
And AllPost.PostID = s2_Scrutiny.ReferenceID
), Temp1
AS
(
Select Distinct
s.DocumentID
,Likeness = 99999999
From Temp0 s
Where #SearchText != '' And #SearchText = ISNULL(s.Code, s.DocumentID)
Union
Select Distinct
s.DocumentID
,Likeness = SUM(ts.[Length])
From
Temp0 s
Join s2_TextSegment ts On
ts.TableName = N's2_Document'
And ts.FieldName = N'Subject'
And ts.RecordID = s.DocumentID
Where #SearchText != '' And #SearchText != ISNULL(s.Code, s.DocumentID)
Group by s.DocumentID
Union
Select Distinct
s.DocumentID
,Likeness = 1
From Temp0 s
Where #SearchText = ''
)
, Temp2
AS
(
Select t0.*, t1.Likeness
From
Temp0 t0
Join Temp1 t1 On t0.DocumentID = t1.DocumentID
)
Insert Into #temp0 (DocumentID, Likeness, ParentScrutinyID)
Select DocumentID, Likeness, ParentScrutinyID From Temp2
DECLARE #temp1 TABLE (
DocumentID int
, Likeness int
)
If #independentPostExists = 0
Begin
Insert Into #temp1 (DocumentID, Likeness)
Select
t.DocumentID
, t.Likeness
From
#temp0 t
End
ELSE
Begin--حوزه مستقلی تعریف شده باشد
--انتقال حوزه فعال باشد
Insert Into #temp1 (DocumentID, Likeness)
Select
t.DocumentID
, t.Likeness
From
#temp0 t
Join s2_Scrutiny parentScrutiny On parentScrutiny.ScrutinyID = t.ParentScrutinyID
Join s2_ScrutinyItem sci On sci.ScrutinyItemID = parentScrutiny.ScrutinyItemID
Where
sci.TransferArea = 1
-- شخص جاری در حوزه ارجاع دهنده باشد
Insert Into #temp1 (DocumentID, Likeness)
Select
t.DocumentID
, t.Likeness
From
#temp0 t
Join s2_Scrutiny parentScrutiny On parentScrutiny.ScrutinyID = t.ParentScrutinyID
Join Temp_SubalternPost tsp1 On tsp1.Subaltern_PostID = parentScrutiny.ScrutinierID
Join Temp_SubalternPost tsp2 On tsp2.Superior_PostID = tsp1.Superior_PostID
Where
tsp1.Superior_NearestIndependent = 1
And tsp2.Subaltern_PostID = #PersonalPostID
--And Not Exists(Select 1 From #temp0 tt Where tt.DocumentID = t.DocumentID)
End
Select Count(Distinct t.DocumentID) From #temp1 t Where Likeness > 0
END--end procedure
GO
This code takes 26 seconds:
exec sp_executesql N'Exec [dbo].[s2_GetReceivedDocumentsCount] #username=N'admin', #Filter1ID=N'12',#Filter1Value=N'17658'
BUT :
I tested this code for another state but returned 22,000 records in 3 seconds
exec sp_executesql N'Exec [dbo].[s2_GetReceivedDocumentsCount] #username=N'admin'
In this code I removed the #Filter1ID=N'12',#Filter1Value=N'17658'
When I remove this #Filter1ID it not enter here:
And (#Filter1ID = ''
Or Exists(
Select 1
From
s2_FieldValue fv
Join s2_Field f On f.FieldID = fv.FieldID
Where
fv.DocumentID = s.DocumentID
And fv.FieldID = #Filter1ID
And (
(f.FieldTypeID in (0, 5/*فیلد محاسباتی*/) And fv.[Value] = #Filter1Value)
Or (f.FieldTypeID = 3 And Cast(fv.[FieldOptionID] as nvarchar(max)) = #Filter1Value)
Or (f.FieldTypeID in(1,2,4))
)
))
Now I'm sure problem is here. But where is it? Where is the problem?
While correlated EXISTS clauses can be a real problem, your overall SP is such a dogs breakfast that I think you should focus on other aspects first:
Do not use LIKE to match a list of numeric values:
(N',' + #States + N',') Like (N'%,' + Cast(s.StateID as nvarchar(max)) + ',%'))
Since you already utilise string splitting function, you should split input value into a table variable of stateIDs (make sure that data type is the same as s.StateID and join it. Do the same for #Senders.
Minimise the use of OR as this kills performance really quickly:
This And (#Date1 = '' Or s.RegistrationDate >= #Date1) should be replaced by:
SET #Date1 = CASE WHEN '' THEN '01-Jan-1753' ELSE #Date1 END and then in your query you can simply have And s.RegistrationDate >= #Date1.
For #Date2 use the maximum value as per DATETIME reference.
Get rid of NVARCHAR( MAX ). Unless you realistically expect input values to be more than 4000 characters, you should use NVARCHAR( 2000 ) or something smaller.
There is a major performance difference between UNION and UNION ALL. Make sure you use UNION ALL unless you need to remove duplicate records. See this
And lastly EXISTS: without fully knowing your table structure and being able to run the query myself I cannot see a way of removing it, such that it will definitely improve performance.
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/
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:
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,',',''',''')+''''