Simplify SQL where exists in clause - sql-server

I want to simplify the below given procedure especially I want to remove most of the where clause filters such as IN and exists clauses.
For that, I have used a CTE and also declare a temp table and used it to get the select query that was talking long time since it was in where in clause. I would appreciate if you could show me some tricks in order to simplify this query.
ALTER PROCEDURE dbo.GetMappingBranchScenarios
#Mapping INT
#UserId INT= NULL
#BranchId INT = NULL
SELECT
BS.BranchId,
NULLIF( CC.Code, '' ) AS Code,
BS.BranchName,
BS.Active
FROM
Branch BS
LEFT OUTER JOIN
Code CC ON CC.BranchId = BS.BranchId
LEFT OUTER JOIN
BranchRule BRE ON BRE.MappingId = #Mapping
AND BRE.BranchId = BS.BranchId
WHERE
(BS.Active = 1
OR EXISTS (SELECT * FROM BranchRule BRE
WHERE BRE.BranchId = BS.BranchId
AND BRE.BranchId > 0
AND BRE.MappingId = #MappingId))
AND (#UserId IS NULL
OR BS.BranchId IN (SELECT BranchId
FROM branch2mapping.dbo.ListBranch(#UserId))
OR EXISTS (SELECT 1 FROM dbo.SecondaryMapping
WHERE Id = #UserId AND Admin = 1))
AND BS.BranchId = (CASE WHEN BranchId is NULL THEN BS.BranchID ELSE #BranchId END)
AND CC.Code = (CASE WHEN #Code IS NULL THEN CC.Code ELSE #Code END)
ORDER BY
CC.Code ASC
What I have done so far :
IF OBJECT_ID('tempdb..#Temp', 'U') IS NOT NULL
DROP TABLE #Temp
CREATE TABLE #Temp (BranchId INT)
SELECT BranchId
FROM branch2mapping.dbo.ListBranch(#UserId)
;WITH CTE AS
(
SELECT
BS.BranchId,
NULLIF(CC.Code, '' ) AS Code,
BS.BranchName, BS.Active
FROM
Branch BS
LEFT OUTER JOIN
Code CC ON CC.BranchId = BS.BranchId
LEFT OUTER JOIN
BranchRule BRE ON BRE.MappingId = #Mapping
AND BRE.BranchId = BS.BranchId
)
SELECT *
FROM CTE
WHERE
(CTE.Active = 1
OR EXISTS (SELECT * FROM BranchRule BRE
WHERE BRE.BranchId = CTE.BranchId
AND BRE.BranchId > 0
AND BRE.MappingId = #MappingId))
AND (#UserId IS NULL
OR BS.BranchId IN (SELECT * FROM #Temp)
OR EXISTS (SELECT 1 FROM dbo.SecondaryMapping
WHERE Id = #UserId AND Admin = 1)
)
AND BS.BranchId = (CASE WHEN BranchId is NULL THEN CTE.BranchID ELSE #BranchId END)
AND CTE.Code = (CASE WHEN #Code IS NULL THEN CTE.Code ELSE #Code END)
ORDER BY
CTE.Code ASC
Thank you for all your help.

Could you try if this is faster and still returning the same values with different filtering criteria?
ALTER PROCEDURE dbo.GetMappingBranchScenarios
#Mapping INT
#UserId INT= NULL
#BranchId INT = NULL
DECLARE #IsRuleExists BIT;
DECLARE #IsUrerADmin BIT;
IF EXISTS
(
SELECT 1
FROM Branch BS
INNER JOIN BranchRule BRE
ON BRE.BranchId = BS.BranchId
AND BRE.BranchId > 0
AND BRE.MappingId = #MappingId
)
BEGIN;
SET #IsRuleExists = 1;
END;
IF EXISTS
(
SELECT 1
FROM dbo.SecondaryMapping
WHERE Id = #UserId AND Admin = 1
) OR #UserId IS NULL
BEGIN;
SET #IsUrerADmin = 1;
END;
CREATE TABLE #Branches
(
[BranchId] INT
);
INSERT INTO #Branches ([BranchId])
SELECT BranchId
FROM branch2mapping.dbo.ListBranch(#UserId);
SELECT
BS.BranchId,
NULLIF( CC.Code, '' ) AS Code,
BS.BranchName,
BS.Active
FROM Branch BS
LEFT OUTER JOIN Code CC
ON CC.BranchId = BS.BranchId
WHERE
(
BS.Active = 1 OR #IsRuleExists = 1
)
AND
(
#IsUrerADmin = 1
OR
BS.BranchId IN (SELECT BranchId FROM #Branches)
)
AND BS.BranchId = (CASE WHEN BranchId is NULL THEN BS.BranchID ELSE #BranchId END)
AND CC.Code = (CASE WHEN #Code IS NULL THEN CC.Code ELSE #Code END)
ORDER BY CC.Code ASC;

Related

Using DECLARE while creating a VIEW?

The literature says that the declare statement is not compatible with creating a View. How do I get around it?
My declare statement looks like:
DECLARE #risk_5 TABLE (Code VARCHAR(100));
INSERT INTO #risk_5 (Code) VALUES ('AA'),('BB'),('CC');
and is then used within a select statement:
SELECT
id,
CASE
WHEN a.[10_2_1_Country] IN (SELECT Code from #risk_5)
THEN '3'
END AS Risk_Country5
FROM x
The recommendation is to pack the declare into a CTE or a stored procedure.
With both these recommendations though, I do not understand how to connect the two? What am I missing?
If you need to use variable try to use stored procedures, if you write a select query in the stored procedure you can get the data too. And you can use declare inside.
I use this way in my solution e.g.
CREATE PROCEDURE [dbo].[GetLoadSiteMass]( #month INT,
#year int,
#storageId int,
#parent nvarchar(50),
#materialSourceId nvarchar(100),
#complexIds nvarchar(50))
AS
BEGIN
DECLARE #MonthPrev int
DECLARE #YearPrev int
SET #MonthPrev = CASE WHEN #Month = 1 THEN 12 ELSE #Month - 1 END
SET #YearPrev = CASE WHEN #Month = 1 THEN #Year - 1 ELSE #Year END
declare #WagonLoadSiteId int
set #WagonLoadSiteId = (select top 1 CarriageLoadSiteId from CarriageLoadSite where LoadSiteType = 2);
DECLARE #loadSide nvarchar(10), #result decimal(18,3)
SET #loadSide=cast( #storageId as nvarchar(50));
WITH CarriageLoadSiteTreeView (
[CarriageLoadSiteId],RootId,RootName,[Code], Name, ParentID, [LoadSiteType],IsDelete,
CodeSAP,DepartmentId, Capacity, MinLimit, MaxLimit, LoadSitePlaceTypeId) AS
(
SELECT [CarriageLoadSiteId],
[CarriageLoadSiteId] RootId,
Name RootName,
[Code],
Name,
ParentID,
[LoadSiteType],
[IsDelete],
CodeSAP,
DepartmentId,
Capacity,
MinLimit,
MaxLimit,
LoadSitePlaceTypeId
FROM CarriageLoadSite WITH(NOLOCK)
WHERE ISNULL(ParentID,0) =isnull(#storageId,0) AND Isdelete!=1
UNION ALL
SELECT d.[CarriageLoadSiteId],
q.RootId RootId,
RootName RootName,
d.[Code],
d.Name,
d.ParentID,
d.[LoadSiteType],
d.[IsDelete],
d.CodeSAP,
d.DepartmentId,
d.Capacity,
d.MinLimit,
d.MaxLimit,
d.LoadSitePlaceTypeId
FROM CarriageLoadSite AS d WITH(NOLOCK)
INNER JOIN CarriageLoadSiteTreeView AS q ON d.ParentID = q.[CarriageLoadSiteId] WHERE d.IsDelete!=1
)
SELECT
ComplexId,
RootId Id,
cast(RootId as nvarchar(8))+'|Sclad'+IIF(RootId=max(R.CarriageLoadSiteId),'|finish','') [Uid],
RootName CarriageLoadSiteName,
ROUND(SUM(AMOUNT-movement-consumption)/1000,3) Amount,
cast(1 as bit) hasChildren,
T.FullPathId Path,
UparentId=IIF(#parent is null,'',#parent),
[Type]=0,
Petal = IIF(RootId=max(R.CarriageLoadSiteId),'|Sclad|finish','')
FROM (
SELECT
RootId
,RootName
,t.CarriageLoadSiteId
,t.MaterialId
,YEAR(t.Period) [Year]
,MONTH(t.Period) [Month]
,round( case when (t.Amount=0 or t.Amount is null) and (tt.Type=0 or [TypeAmountCarriage]=1 )then carr.[CertifNetto]else t.Amount end ,0 )[Amount]
,t.UnitId
, CarriageId
, tt.TurnoverTypeId
,round(dbo.GetMovementByTurnOverWithTempValue(t.turnoverid),5) movement
,dbo.GetConsumptionByTurnOver(t.turnoverid) consumption
,0 stockBegin
,round(t.Amount,0 ) CommingAmount
,case when (t.Amount=0 or t.Amount is null) and tt.Type=0 then 1 else 0 end [IsNotConfirmed]
,[TypeAmountCarriage]
,M.ComplexId
FROM Turnover t WITH(NOLOCK)
INNER JOIN TurnoverType tt ON tt.TurnoverTypeId = t.TurnoverTypeId
INNER JOIN CarriageLoadSiteTreeView l ON l.CarriageLoadSiteId = t.CarriageLoadSiteId
INNER JOIN [Carriages] carr on carr.[CarriagesID]=t.[CarriageId]
INNER JOIN Material M on M.MaterialID=t.MaterialId
WHERE YEAR(t.Period) = #Year AND
MONTH(t.Period) = #Month AND
l.LoadSiteType = 0 AND
tt.type in (0,5,4) AND
isclear=0 AND
M.MaterialSourceID in (select value from string_split(#materialSourceId, ','))
UNION ALL
SELECT RootId
,RootName
,s.CarriageLoadSiteId
,s.MaterialId
,#Year [Year]
,#Month [Month]
,round(s.Amount,0)
,s.UnitId
,CarriageId
,[TurnoverTypeId]
,round(dbo.GetMovementByStock(s.StockId),5) movement
,dbo.GetConsumptionByStock(s.StockId) consumption
,round(s.Amount,0)-s.spendStock
,0
,0 [IsNotConfirmed]
,[TypeAmountCarriage]
,M.ComplexId
FROM Stock s
INNER JOIN CarriageLoadSiteTreeView l ON l.CarriageLoadSiteId = s.CarriageLoadSiteId
INNER JOIN Material M on M.MaterialID=s.MaterialId
WHERE s.[Year] = #YearPrev AND
s.[Month] = #MonthPrev AND
s.[Type] = 0 AND
l.LoadSiteType = 0 AND
amount >0 AND
isclear=0 AND
M.MaterialSourceID in (select value from string_split(#materialSourceId, ','))
) as R
INNER JOIN CariageLoadSiteTree T on T.CarriageLoadSiteId=RootId
INNER JOIN string_split(#complexIds, ',') MM ON CAST(MM.value AS int) = R.ComplexId
WHERE AMOUNT-movement-consumption>10
GROUP BY RootName,RootId,ComplexId, T.FullPathId
ORDER BY RootName

Stored procedure always returns same query

I tried to write a SQL query to get results with some parameters, but when I send parameters, it doesn't work. It always returns the last query in if else condition statement.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[sp_RealEstatesList]
#TransCode NVARCHAR(5),
#CatUrl NVARCHAR(255) = NULL,
#ForSaleItem BIT = NULL,
#NewItem BIT = NULL,
#ItemOfDay BIT = NULL,
#Random BIT = NULL,
#Top INT = NULL
AS
SET NOCOUNT ON
SET XACT_ABORT ON
SET FMTONLY OFF
BEGIN TRAN
IF (OBJECT_ID('tempdb..#TempTable') IS NOT NULL)
BEGIN
DROP TABLE #TempTable
END
SELECT
R.[ID],
RT.[Title],
R.[Price],
R.[NewItem],
R.[ForSaleItem],
R.[ItemOfDay],
R.[Url],
(SELECT TOP 1 CC.Url
FROM [dbo].[Category] CC
JOIN [dbo].[LinkTypes] LLT ON LLT.[MainID] = CC.ID
JOIN [dbo].[Links] LL ON LL.[LinkTypeID] = LLT.[ID]
JOIN [dbo].[RealEstates] RR ON RR.[ID] = LL.LinkID
WHERE LLT.[LinkedTypeID] = 17
AND LLT.[MainTypeID] = 1
AND RR.ID = R.[ID]) AS 'CatUrl',
(SELECT TOP 1
(SELECT TOP 1 XC.Url
FROM Category XC
JOIN [dbo].[LinkTypes] LLT ON LLT.[MainID] = XC.ID
JOIN [dbo].[Links] LL ON LL.[LinkTypeID] = LLT.[ID]
WHERE LLT.[LinkedTypeID] = 1
AND LLT.[MainTypeID] = 1
AND LL.LinkID = CC.ID)
FROM [dbo].[Category] CC
JOIN [dbo].[LinkTypes] LLT ON LLT.[MainID] = CC.ID
JOIN [dbo].[Links] LL ON LL.[LinkTypeID] = LLT.[ID]
JOIN [dbo].[RealEstates] RR ON RR.[ID] = LL.LinkID
WHERE LLT.[LinkedTypeID] = 17
AND LLT.[MainTypeID] = 1
AND RR.ID = R.[ID]) AS 'PCatUrl'
INTO
#TempTable
FROM
[dbo].[RealEstates] R
JOIN
[dbo].[RealEstatesT] RT ON R.[ID] = RT.[RealEsID]
JOIN
[dbo].[LinkTypes] LT ON LT.[MainTypeID] = 17
JOIN
[dbo].[Links] L ON L.[LinkTypeID] = LT.[ID]
JOIN
[dbo].[Translation] TR ON TR.[ID] = RT.[TransID]
WHERE
R.[Active] = 1
AND R.[Deleted] = 0
AND RT.[Deleted] = 0
AND LT.[LinkedTypeID] = 5
AND LT.[MainID] = R.[ID]
AND TR.[ShortName] = #TransCode
GROUP BY
R.[ID], RT.[Title], R.[Price], R.[NewItem], R.[ForSaleItem], R.[ItemOfDay], R.[Url]
if (#Top = null or #Top = 0)
begin
set #Top = 100000;
end
if(#NewItem != null)
begin
select TOP (#Top) [ID],[Title],[Price],[NewItem],[ForSaleItem],[CatUrl],[PCatUrl],[ItemOfDay],[Url]
from #TempTable
where NewItem = #NewItem
order by case when #Random = 1 then NEWID() end
end
else if(#ForSaleItem != null)
begin
select TOP (#Top) [ID],[Title],[Price],[NewItem],[ForSaleItem],[CatUrl],[PCatUrl],[ItemOfDay],[Url]
from #TempTable
where ForSaleItem = #ForSaleItem
order by case when #Random = 1 then NEWID() end
end
else if(#CatUrl != null)
begin
select TOP (#Top) [ID],[Title],[Price],[NewItem],[ForSaleItem],[CatUrl],[PCatUrl],[ItemOfDay],[Url]
from #TempTable
where CatUrl = #CatUrl or PCatUrl = #CatUrl
order by case when #Random = 1 then NEWID() end
end
else if(#ItemOfDay != null)
begin
select TOP (#Top) [ID],[Title],[Price],[NewItem],[ForSaleItem],[CatUrl],[PCatUrl],[ItemOfDay],[Url]
from #TempTable
where ItemOfDay = #ItemOfDay
order by case when #Random = 1 then NEWID() end
end
else
begin
select TOP (#Top) [ID],[Title],[Price],[NewItem],[ForSaleItem],[CatUrl],[PCatUrl],[ItemOfDay],[Url]
from #TempTable
order by case when #Random = 1 then NEWID() end
end
COMMIT
Transcode and Random parameters work well but CatUrl, ForSaleItem, NewItem, ItemOfDay parameters does not work. It always returns the last query in if else condition statement.
Hope you can help. I'm waiting for your answers.
edit :
I changed all my null checks like "NULLIF(#Top, '') IS NULL" and now if statements works well.

How to optimise this stored procedure?

I have the stored procedure below and I am having two issues with it
It is running very slowly, and
It is returning a blank result set
The idea for the stored procedure is to do a sequence check to find if any account numbers have not been assigned.
Step 1 loops through all the branches and builds up the tempdetails table.
After that it creates the list of all the numbers that have been used and uses that to delete everything that exists to leave a list of those accountnumbers that do not exist,
But een though I know there are missing account numbers, aside from the exceptionally long tun time it is returning a blank result set.
Anyone have any ideas what is going wrong with it?
Thanks
ALTER PROCEDURE [dbo].[PracticeFindMissingSequenceDetail]
#pracId VARCHAR(128),
#Prefix VARCHAR(256)
AS
BEGIN
DECLARE #TempDetails TABLE (SequenceCheck VARCHAR(24),
Prefix VARCHAR(4),
BranchName VARCHAR(256),
RisStatus VARCHAR(256),
Rislink VARCHAR(256)
);
DECLARE #Branchlist TABLE (BranchId INTEGER,
BranchName VARCHAR(256),
BranchPrefix VARCHAR(4),
PrefixLength INT,
SequenceLength INT
);
DECLARE #TempPatNo TABLE (Patno VARCHAR(24));
DECLARE #BranchName VARCHAR(256),
#BranchPrefix VARCHAR(256),
#PrefixLength INT,
#BranchId INT,
#SequenceLength INT,
#rangestart INTEGER,
#rangeend INTEGER,
#rangenow INTEGER,
#startDate DATETIME,
#Patno VARCHAR(128),
#FormatZeroes VARCHAR(3),
#CurrentLength INT,
#RangeString VARCHAR(256);
INSERT INTO #Branchlist (BranchId, BranchName, BranchPrefix, PrefixLength, SequenceLength)
SELECT
b.id, b.name, b.prefix, PrefixLength, SequenceLength
FROM
Branch b
INNER JOIN
Practice pr ON pr.id = b.practiceid
INNER JOIN
[Sequence] s ON s.id = b.id
WHERE
pr.APIKey = #pracID
AND b.inactive = 0
AND b.prefix = #Prefix
/* insert values for each branch into table*/
DECLARE BranchPointer CURSOR FOR
SELECT BranchID FROM #Branchlist
OPEN BranchPointer
FETCH NEXT FROM BranchPointer INTO #BranchId
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #BranchPrefix = (SELECT BranchPrefix
FROM #Branchlist
WHERE BranchId = #BranchId)
SELECT #PrefixLength = (SELECT PrefixLength
FROM #Branchlist
WHERE BranchId = #BranchId)
SELECT #SequenceLength = (SELEct SequenceLength
FROM #Branchlist
WHERE BranchId = #BranchId)
/* Set the starting date from the sequence */
SELECT #startDate = (SELECT MIN(MinimumSequenceDate)
FROM [Sequence] s
WHERE s.id = #BranchId)
/*get the earliest number in the sequence from the startdate*/
SELECT #rangestart = (SELECT MIN(SUBSTRING(v.bookingnumber, 3, LEN(bookingnumber)))
FROM Visit v
INNER join Branch b ON b.id = v.branchid
INNER join Practice pr ON pr.id = b.practiceid
WHERE pr.APIKey = #pracId
AND LEFT(v.bookingnumber, 2) = #Prefix
AND v.date >= #startDate
AND v.branchid = #BranchId);
/*get the latest number in the sequence from the startdate*/
SELECT #rangeend = (SELECT MAX(SUBSTRING(v.bookingnumber, 3, LEN(bookingnumber)))
FROM Visit v
INNER JOIN Branch b ON b.id = v.branchid
INNER JOIN Practice pr ON pr.id = b.practiceid
WHERE pr.APIKey = #pracId
AND LEFT(v.bookingnumber, 2) = #Prefix
AND v.date >= #startDate
AND v.branchid = #BranchId);
SET #RangeNow = #rangestart
WHILE #rangenow < #rangeend
BEGIN
/*check if leading zeroes are needed in the number and add them if needed*/
SET #RangeString = CAST(#RangeNow AS VARCHAR(256))
SET #CurrentLength = LEN(#rangenow)
IF #prefixlength + #currentlength < #SequenceLength
WHILE #CurrentLength + #PrefixLength < #SequenceLength
BEGIN
SET #RangeString = '0' + #RangeString;
SET #currentlength = LEN(#RangeString);
END;
/*Insert full sequence into temporary table*/
INSERT INTO #TempDetails (SequenceCheck, Prefix, BranchName)
SELECT #Prefix + #RangeString, #Prefix, #BranchName
SET #rangenow =#rangenow+1
END;
FETCH NEXT FROM BranchPointer INTO #BranchName
END
CLOSE BranchPointer
DEALLOCATE BranchPointer
/*delete existing sequence numbers from table*/
INSERT INTO #TempPatNo (PatNo)
SELECT BookingNumber
FROM Visit v1
INNER JOIN Branch b1 ON b1.id = v1.branchid
INNER JOIN Practice pr1 ON pr1.id = b1.practiceid
WHERE pr1.APIKey = #pracId
DELETE #TempDetails
WHERE sequencecheck IN (SELECT patNo FROM #TempPatNo)
/*Insert the status and link for error messages*/
UPDATE #tempDetails
SET RisStatus = (SELECT Status
FROM RISErrors r
INNER JOIN Practice pr ON pr.id = r.PracticeId
WHERE pr.APIKey = #pracId
AND VisitNumber = SequenceCheck
AND r.id = (SELECT MAX(r1.id)
FROM RISErrors r1
INNER JOIN Practice pr1 ON pr1.id = r1.PracticeId
WHERE pr1.APIKey = #pracId
AND VisitNumber = SequenceCheck)),
RisLink = 'http://billing.cryanic.co.za/Clinton/RISErrors?searchquery=' + SequenceCheck
/*return missing numbers into sequence control callong procedure*/
SELECT DISTINCT SequenceCheck, RisStatus, Rislink
FROM #TempDetails
END
After reading your procedure, I made some assumptions:
there is a one-to-one relationsship between sequence and branch
the visits are the details of a sequence
the BranchName and BranchPrefix aren't needed.
I recommend to not do lookups by BranchID but instead retrieve the values from the cursor query. The table BranchList isn't needed, you can base the cursor on the query directly. Also, the TempPatNo table can be avoided.
Here's what I have come up with:
ALTER PROCEDURE [dbo].[PracticeFindMissingSequenceDetail]
#pracId VARCHAR(128),
#Prefix VARCHAR(256)
AS
BEGIN
DECLARE #TempDetails TABLE (
BranchID INT,
SequenceCheck VARCHAR(24),
RisStatus VARCHAR(256),
Rislink VARCHAR(256)
);
DECLARE
#PrefixLength INT,
#BranchId INT,
#SequenceLength INT,
#rangestart INTEGER,
#rangeend INTEGER,
#rangenow INTEGER,
#startDate DATETIME;
/* insert values for each branch into table*/
DECLARE BranchPointer CURSOR FOR
SELECT b.id, PrefixLength, SequenceLength, s.MinimumSequenceDate
FROM Branch b
INNER JOIN Practice pr ON pr.id = b.practiceid
INNER JOIN [Sequence] s ON s.id = b.id
WHERE pr.APIKey = #pracID
AND b.prefix = #Prefix
AND b.inactive = 0
OPEN BranchPointer
FETCH NEXT FROM BranchPointer INTO #BranchId, #PrefixLength, #SequenceLength, #startDate
WHILE ##FETCH_STATUS = 0
BEGIN
/*get the earliest and latest number in the sequence from the startdate*/
SELECT
#rangestart = MIN(SUBSTRING(v.bookingnumber, 3, LEN(v.bookingnumber))),
#rangeend = MAX(SUBSTRING(v.bookingnumber, 3, LEN(v.bookingnumber)))
FROM Visit v
WHERE v.branchid = #BranchId
AND v.date >= #startDate
AND LEFT(v.bookingnumber, 2) = #Prefix;
SET #RangeNow = #rangestart
WHILE #rangenow < #rangeend
BEGIN
/*Insert full sequence into temporary table*/
INSERT INTO #TempDetails (BranchID, SequenceCheck)
SELECT #BranchId,
#Prefix + REPLICATE('0', #SequenceLength-#PrefixLength-LEN(#rangenow)) + CAST(#RangeNow AS VARCHAR(256));
SET #rangenow =#rangenow+1
END;
FETCH NEXT FROM BranchPointer INTO #BranchId, #PrefixLength, #SequenceLength, #startDate
END
CLOSE BranchPointer
DEALLOCATE BranchPointer
/*delete existing sequence numbers from table*/
DELETE FROM #TempDetails
FROM #TempDetails t
INNER JOIN Visit v ON t.BranchID = v.branchid
WHERE t.SequenceCheck = v.BookingNumber
/*Insert the status and link for error messages*/
UPDATE #tempDetails
SET RisStatus = (SELECT Status
FROM RISErrors r
INNER JOIN Practice pr ON pr.id = r.PracticeId
WHERE pr.APIKey = #pracId
AND VisitNumber = SequenceCheck
AND r.id = (SELECT MAX(r1.id)
FROM RISErrors r1
INNER JOIN Practice pr1 ON pr1.id = r1.PracticeId
WHERE pr1.APIKey = #pracId
AND VisitNumber = SequenceCheck)),
RisLink = 'http://billing.cryanic.co.za/Clinton/RISErrors?searchquery=' + SequenceCheck
/*return missing numbers into sequence control callong procedure*/
SELECT DISTINCT SequenceCheck, RisStatus, Rislink
FROM #TempDetails
END

Performance issue because of left join and multiple where clause

Here is the procedure
create PROCEDURE [dbo].[sample1] (
#param1 varchar(20) ,
#param2 VARCHAR(5),
#param3 varchar(max) = NULL,
#param4 varchar(max) = NULL,
#param5 varchar(max) = NULL,
#param6 bit = 1,
#param7 varchar(max) = NULL,
#param8 bit = 1,
#param9 varchar(max) = NULL,
#param10 varchar(max) = NULL,
#param11 varchar(max) = NULL,
#param12 varchar(5) = 'OP',
#param13 varchar(max) = NULL,
#TOP int = 101,
#SORTFIELD varchar(20) = 'DESCRIPTION',
#SORTDIRECTION varchar(5) = 'ASC'
)
AS
BEGIN
DECLARE
#NOW VARCHAR(10)=(SELECT CONVERT(varchar(10), GETDATE(), 112)),
#PHYSNAME VARCHAR(50)='',
#PHYPARAMS CHAR(1)='N'
/*********************************/
SELECT CPPACKAGE_PARAMS, MIN(CODE) AS MinCode, MAX(CODE) AS MaxCode
INTO #SNCPPKG_PARAMS_DTLS
FROM SNCPPKG_PARAMS_DTLS
WHERE CODETYPE = 5
GROUP BY CPPACKAGE_PARAMS
SELECT *
INTO #SNCPPACKAGERL
FROM SNCPPACKAGERL
WHERE DOMDEF = #param1
--SELECT *
--INTO #SNCPPROCDEF
--FROM SNCPPROCDEF
--WHERE DOMDEF = #param1
--SELECT *
--INTO #SNCPDIAGDEF
--FROM SNCPDIAGDEF
--WHERE DOMDEF = #param1
/*********************************/
SELECT
#PHYPARAMS=[ParamaterValue]
FROM [dbo].[sntbFacilityParamaters] with(nolock)
where [ParamaterTypeId] =
(SELECT TOP 1 [ParamaterTypeId]
FROM [dbo].[sntbParamaterTypeRef] with(nolock)
where ParamaterTypeName ='Physician Specific Packages')
and facid = #param2
IF( ISNULL(#PHYPARAMS ,'N')='N')
BEGIN
SET #param11=''
END
SET NOCOUNT ON;
CREATE TABLE #tempGLT1DET (CODEFROM VARCHAR(32))
INSERT INTO #tempGLT1DET
SELECT A.CODEFROM FROM snlocGLT1DET A with(nolock)
INNER JOIN snlocGLTABLE1 B with(nolock) ON A.GLTABLE1 = B.SYSKEY
WHERE A.CODETYPE IN ('4', '5')
AND NAME = 'AMA HCPCS'
AND (B.EFF_DATE <= #NOW OR B.EFF_DATE='')
AND (B.TRM_DATE >= #NOW OR B.TRM_DATE='')
AND (B.ACTIVATION_DT <= #NOW)
if(#top>300)
BEGIN
SET #top=300
END
IF(ISNULL(#param5,'')='' )
BEGIN
SET #param6=0
END
IF( ISNULL(#param7,'')='')
BEGIN
SET #param8=0
END
SELECT * INTO #TEMPPACKAGECOMPLETE
FROM
(SELECT --TOP(#TOP)
A.SYSKEY,
A.MCOMMORD,
A.SERVTYPE,
A.DESCRIPTION,
isnull(A.some_ver,'9') as some_ver,
A.ER,
A.OUTPATIENT,
A.INPATIENT,
A.DRG,
A.EFF_DATE,
A.TRM_DATE,
A.DOMDEF,
A.FINCLASS,
A.FORMORD,
A.AUDIT,
A.ALTDESC,
A.CODE,
B.TOTALCHARGE,
--null AS PHYSNAME,
A.PHYSNAME,
--NULL AS NPI,
A.NPI,
A.CPPACKAGE_PARAMS,A.PROCCODE,A.HCPCSRATES
--,row_number() over(partition BY A.SYSKEY
-- ORDER BY A.SYSKEY) rn
FROM
(SELECT *
FROM
(SELECT --TOP(#TOP)
CPPACKAGEDEF.SYSKEY,
isnull(CPPACKAGEDEF.some_ver,'9') as some_ver,
CPPACKAGEDEF.MCOMMORD,
CPPACKAGEDEF.SERVTYPE,
CPPACKAGEDEF.DESCRIPTION AS 'DESCRIPTION',
CPPACKAGEDEF.ER,
CPPACKAGEDEF.OUTPATIENT,
CPPACKAGEDEF.INPATIENT,
CPPACKAGEDEF.DRG,
CPPACKAGEDEF.EFF_DATE,
CPPACKAGEDEF.TRM_DATE,
CPPACKAGEDEF.DOMDEF,
CPPACKAGEDEF.FINCLASS,
CPPACKAGEDEF.FORMORD,
CPPACKAGEDEF.AUDIT,
CPPACKAGEDEF.ALTDESC,
REVDET.REVCODE, --REMOVE
P.PROCCODE,REVDET.HCPCSRATES,
CODE = CASE WHEN ISNULL(params.MinCode,'') = '' THEN ''
WHEN params.MinCode = params.MaxCode THEN params.MinCode
ELSE 'Multiple' END,
-- CODE = CASE WHEN
--(SELECT count(1)
-- FROM SNCPPKG_PARAMS_DTLS d with(nolock)
-- WHERE CPPACKAGE_PARAMS = CPPACKAGEDEF.CPPACKAGE_PARAMS
-- AND CODETYPE = 5) > 1 THEN 'Multiple' ELSE ISNULL(
-- (SELECT CODE
-- FROM SNCPPKG_PARAMS_DTLS d with(nolock)
-- WHERE CPPACKAGE_PARAMS = CPPACKAGEDEF.CPPACKAGE_PARAMS
-- AND CODETYPE = 5), '') END,
CPPACKAGEDEF.CPPACKAGE_PARAMS,
ISNULL(SC_TYPE,'R')AS SC_TYPE
FROM SNCPPACKAGEDEF AS CPPACKAGEDEF with(nolock)
LEFT JOIN #SNCPPKG_PARAMS_DTLS AS params ON params.CPPACKAGE_PARAMS = CPPACKAGEDEF.CPPACKAGE_PARAMS
LEFT JOIN #SNCPPACKAGERL REVDET ON REVDET.CPPACKAGEDEF= CPPACKAGEDEF.syskey-- and REVDET.domdef= #param1
--start:rajesh:for diag and proc
left join SNCPPROCDEF p with (nolock) on (P.CPPACKAGEDEF = CPPACKAGEDEF.syskey) and p.domdef= #param1
left join SNCPDIAGDEF d with (nolock) on (d.CPPACKAGEDEF = CPPACKAGEDEF.syskey) and d.domdef= #param1
--LEFT JOIN SNCPPACKAGERL pkgRL ON pkgRL.CPPACKAGEDEF= C.syskey
where
(
((isnull(#param5,'')='') or (d.DIAGCODE like #param5+'%'))
and
((isnull(#param7,'')='') or (p.PROCCODE like #param7+'%'))
)
AND
(
((#param13='9') AND (ISNULL(CPPACKAGEDEF.some_ver,'9')='9')) OR
((#param13='0') AND (ISNULL(CPPACKAGEDEF.some_ver,'9')='0'))
OR
(ISNULL(#param13,'')='')
)
--AND REVDET.
-- AND p.DOMDEF = #param1
--AND d.DOMDEF = #param1
AND
(
ISNULL(#param7,'')=''
OR
(
(#param12='IP' AND ISNULL(#param7,'')<>'')
--AND
--(
--( P.PROCCODE IN
-- ( SELECT DISTINCT DESTCODE FROM snVwCodeXWalk XWALK WHERE XWALK.SOURCECODE = #param10)
--)
--)
)
OR
(
((#param12='OP' OR #param12='ER') AND ISNULL(#param7,'')<>'')
AND
(
REVDET.HCPCSRATES like #param10+'%'
)
)
)
AND
(
(
( (#param5=1 AND #param8=0 )
AND
(d.SEQUENCE=1)
)
--or ISNULL(#param5,'')=''
)
OR
(
((#param8=1 AND #param6=0) AND
(p.SEQUENCE=1) )
--OR ISNULL(#param7,'')=''
)
OR
(
(
(#param5=1 )--AND ISNULL(#param5,'')<>'')
AND (#param8=1)-- AND ISNULL(#param7,'')<>'')
AND (p.SEQUENCE=1 )
AND (d.SEQUENCE=1 )
)
)
OR
(#param5=0 AND #param8=0)
)
--end:rajesh for diag and proc
--where SYSKEY = '126FAQ00249R' and
AND
(
(CPPACKAGEDEF.DESCRIPTION LIKE '%'+#param3+'%')
OR (CPPACKAGEDEF.ALTDESC LIKE '%'+#param3+'%')
OR (ISNULL(#param3,'')='')
)
AND
( (REVDET.REVCODE LIKE #param9+'%') OR (ISNULL(#param9,'')='' ))
AND( (CPPACKAGEDEF.DRG LIKE #param4+'%') OR (ISNULL(#param4,'')='') )
AND
-- ISNULL(CPPACKAGEDEF.SC_TYPE,'R')=
-- CASE WHEN #PHYPARAMS='Y'
-- THEN 'P'
--ELSE
--'R'
--end
(
(#PHYPARAMS='Y' AND CPPACKAGEDEF.SC_TYPE='P' AND ISNULL(#param11,'')<>'' )
OR
(#PHYPARAMS='Y'AND ISNULL(#param11,'')='' )
OR
(#PHYPARAMS='N'AND ISNULL(CPPACKAGEDEF.SC_TYPE,'R')='R' )
)
AND (CPPACKAGEDEF.EFF_DATE <= #NOW OR ISNULL(CPPACKAGEDEF.EFF_DATE,'')='')
AND (CPPACKAGEDEF.TRM_DATE >= #NOW OR ISNULL(CPPACKAGEDEF.TRM_DATE,'')='')
AND CPPACKAGEDEF.DOMDEF=#param1
--AND p.DOMDEF=#param1
--AND d.DOMDEF=#param1
) CPPACKAGEDEF
LEFT JOIN
(SELECT PHYSNAME,
phyPARAMS,
NPI
FROM
(SELECT DISTINCT b.PHYSNAME,
b.NPI,
cp.SYSKEY phyPARAMS,
ROW_NUMBER() OVER (PARTITION BY b.NPI,cp.SYSKEY
ORDER BY b.MDATE DESC) AS rowNum
FROM dbo.BILLPHYS b
INNER JOIN SNCPPACKAGE_PARAMS cp with(nolock) ON cp.NPI = b.NPI
WHERE ISNULL(b.NPI, '') <> '') phy
WHERE phy.rowNum=1) B ON B.phyPARAMS = CPPACKAGEDEF.CPPACKAGE_PARAMS
WHERE (CPPACKAGEDEF.SYSKEY <> ''
AND CPPACKAGEDEF.AUDIT = 'Z')
AND (CPPACKAGEDEF.DOMDEF IN (#param1))
AND (
((CPPACKAGEDEF.INPATIENT = 'Y') AND (#param12='IP'))
OR
((CPPACKAGEDEF.OUTPATIENT = 'Y') AND (ISNULL(#param12,'OP')='OP'))
OR
((#param12='ER' AND CPPACKAGEDEF.OUTPATIENT = 'Y' )AND CONVERT(INT,CPPACKAGEDEF.REVCODE) BETWEEN 450 AND 459)
)
) A
LEFT JOIN
(SELECT SUM(CONVERT(MONEY, LINECHARGE) * UNITS) AS 'TOTALCHARGE', CPPACKAGEDEF FROM
(SELECT LINECHARGE,
UNITS,
CPPACKAGEDEF
FROM #SNCPPACKAGERL with(nolock)) B
GROUP BY CPPACKAGEDEF) B ON A.SYSKEY = B.CPPACKAGEDEF
) A
-- LEFT JOIN SNCPPACKAGERL REVDET ON REVDET.CPPACKAGEDEF= A.syskey AND REVDET.DOMDEF=#param1
WHERE
--rn= 1
--AND
( (A.PHYSNAME LIKE #param11+'%') OR (ISNULL(#param11,'')='' ))
--
--select * from #TEMPPACKAGECOMPLETE
---
--SELECT count(DISTINCT SYSKEY)FROM #TEMPPACKAGE
-- gpant start
Select top (#top) * into #TEMPPACKAGE from (Select *,row_number() over(partition BY SYSKEY
ORDER BY SYSKEY) rn from #TEMPPACKAGECOMPLETE where ((
ISNULL(#param7,'')=''
OR
(
(#param12='IP' AND ISNULL(#param7,'')<>'')
AND
(
( PROCCODE IN
( SELECT DISTINCT DESTCODE FROM snVwCodeXWalk XWALK WHERE XWALK.SOURCECODE = #param10)
)
)
)
OR
(
((#param12='OP' OR #param12='ER') AND ISNULL(#param7,'')<>'')
--AND
--(
-- HCPCSRATES like #param10+'%'
--)
)
) ))t where rn =1
-- --gpant end
SELECT
--count(distinct T.SYSKEY) AS ScSyskey
T.SYSKEY AS ScSyskey,
T.DESCRIPTION AS ScDescription,
T.PHYSNAME AS ScPhysician ,
CASE WHEN ISNULL(#param12 ,'OP')='OP' THEN 'OP'
ELSE
CASE WHEN #param12='IP' THEN 'IP'
ELSE
CASE WHEN #param12='ER' THEN 'ER'
END
END
END ScPatientType,
--'I' AS ScPatientType,
T.DRG AS ScDiagnosis,
T.CODE AS ScPrimaryCdmProcedure ,
CASE WHEN P.DIAG_PRIMARYCODE='Y' THEN P.DIAGCODE ELSE NULL END AS ScPrimaryIcdDiagnosis,
CASE WHEN P.PROC_PRIMARYCODE='Y' THEN P.PROCCODE ELSE NULL END AS ScPrimaryIcdProcedure,
ISNULL(T.TOTALCHARGE, 0) AS ScAmount,
T.MCOMMORD AS ScClaimCount,
C.CODE AS ScCode,
C.CODETYPEDESC AS ScCodeType,
T.DESCRIPTION AS ScCodeDescription,
CAST(C.DATEFROM AS DATETIME) AS ScDateFrom,
CAST(C.DATETO AS DATETIME) As ScDateTo,
REVCODE.UNITS AS CdmUnits,
REVCODE.UNITSORDAYS AS CdmUnitType,
REVCODE.CPT4 AS CdmCode,
REVCODE.MODIFIERS AS CdmModifier,
REVCODE.REVCODE AS CdmRevenueCode,
REVCODE.REVDESC AS CdmDescription,
REVCODE.CHARGECODE AS CdmChargeCode,
REVCODE.LINECHARGE AS CdmPerUnitCharge,
P.DIAGCODE AS IcdDiagCode,
P.DIAG_PRIMARYCODE AS IcdDiagIsPrimary,
P.DIAGDESC AS IcdDiagDescription,
P.PROCCODE AS IcdProcCode,
P.PROC_PRIMARYCODE AS IcdProcIsPrimary,
P.PROCDESCS AS IcdProcDescription,
p.ProcedureSequence,
p.DiagSequence
FROM #TEMPPACKAGE T
LEFT JOIN
(
select distinct x.syskey as CPPACKAGEDEF,
proce.PROCCODE AS PROCCODE,
diag.DIAGCODE AS DIAGCODE,
PROCDESC.PROCDESC AS PROCDESCS ,
DIAGDESC.DIAGDESC AS DIAGDESC,
ISNULL(PROCDESC.ICD_CODE_VERSION,'ICD9Proc') as proccode_version ,
ISNULL(DIAGDESC.ICD_CODE_VERSION,'ICD9Dx') as diagcode_version, --ISNULL(p.DIAGDESC.ICD_CODE_VERSION,'ICD9Dx')
PROCDESC.VALID AS ISPROCVALID,
DIAGDESC.VALID AS ISDIAGVALID,
CASE WHEN PROCE.SEQUENCE =1 THEN 'Y' ELSE 'N' END AS PROC_PRIMARYCODE,
CASE WHEN DIAG.SEQUENCE =1 THEN 'Y' ELSE 'N' END AS DIAG_PRIMARYCODE ,
PROCE.SEQUENCE AS ProcedureSequence,
DIAG.SEQUENCE AS DiagSequence
from
--(
(
select distinct c.syskey as syskey
from snCPPACKAGEDEF C where domdef=#param1
)x
left join SNCPPROCDEF proce on (x.syskey=proce.CPPACKAGEDEF and proce.DOMDEF = #param1)
left join SNCPDIAGDEF diag on (x.syskey=diag.CPPACKAGEDEF and diag.DOMDEF = #param1)
left join SNLOCCP_DTPROC PROCDESC with(nolock) ON (proce.PROCCODE = PROCDESC.PROCCODE and PROCDESC.valid='Y' )
LEFT JOIN SNLOCCP_DTDIAG DIAGDESC with(nolock) ON (diag.DIAGCODE = DIAGDESC.DIAGCODE and DIAGDESC.valid='Y')
) P
ON T.SYSKEY = P.CPPACKAGEDEF
LEFT JOIN
VWCODEDESC AS C ON T.CPPACKAGE_PARAMS = C.CPPACKAGE_PARAMS
LEFT JOIN
(SELECT DISTINCT pkgRL.CPPACKAGEDEF, pkgRL.CHARGECODE, pkgRL.UNITS, pkgRL.UNITSORDAYS, pkgRL.SEQUENCE,
pkgRL.PERRELEVANCE, CAST(ISNULL(pkgRL.MOD1,'') + ','+ ISNULL(pkgRL.MOD2,'') + ','+ ISNULL(pkgRL.MOD3,'')+ ','+ ISNULL(pkgRL.MOD4,'') AS VARCHAR(50)) AS MODIFIERS, pkgRL.UNITWEIGHT,
ISNULL(pkgRL.REVDESC,'Procedure no longer exists!') AS REVDESC, pkgRL.HCPCSRATES,
pkgRL.REVCODE, pkgRL.LINECHARGE, pkgRL.STATCHARGE, pkgRL.CDMCHARGE,
CASE WHEN pkgRL.HCPCSRATES = '' OR pkgRL.HCPCSRATES IN (SELECT CODEFROM FROM #tempGLT1DET) THEN pkgRL.HCPCSRATES ELSE 'Invalid HCPCS Code:' + pkgRL.HCPCSRATES END AS 'CPT4'
FROM #SNCPPACKAGERL pkgRL ) revcode
ON T.SYSKEY = revcode.CPPACKAGEDEF
where
--(ISNULL(p.PROCCODE,'')<>'' OR ISNULL(p.DIAGCODE,'')<>'')
--AND
ISNULL(ISDIAGVALID,'Y')='Y' AND ISNULL(ISPROCVALID,'Y')='Y'
and
(
(
(
(T.some_ver='9' AND ISNULL(p.diagcode_version,'ICD9Dx')='ICD9Dx' )
OR
(T.some_ver='0' AND p.diagcode_version='ICD10CM')
OR
(ISNULL(P.DIAGCODE,'')='')
)
AND
(
(T.some_ver='9' AND ISNULL(p.proccode_version,'ICD9Proc')='ICD9Proc' )
OR
(T.some_ver='0' AND p.proccode_version='ICD10PCS')
OR
(ISNULL(P.PROCCODE,'')='')
)
)
OR
((ISNULL(P.DIAGCODE,'')='')OR(ISNULL(P.PROCCODE,'')='') )
)
ORDER BY CASE
WHEN UPPER(#SORTFIELD) = 'DESCRIPTION' AND
#SORTDIRECTION = 'DESC' THEN T.DESCRIPTION
END DESC,
CASE
WHEN UPPER(#SORTFIELD) = 'DESCRIPTION' AND
#SORTDIRECTION != 'DESC' THEN T.DESCRIPTION
END ASC,
CASE
WHEN UPPER(#SORTFIELD) = 'CHARGECODE' AND
#SORTDIRECTION = 'DESC' THEN
T.SYSKEY
END DESC,
CASE
WHEN UPPER(#SORTFIELD) = 'CHARGECODE' AND
#SORTDIRECTION != 'DESC' THEN
T.SYSKEY
END ASC
END
In the procedure param1 and param2 are mandatory. when I search with the rest of the params, my procedure is giving me average performance(withing 10-12 seconds). But When I search with param10 I am getting the result in 16 minutes which is unacceptable. I have tried to tweak the procedure by changing the where clause positions, implementing temp tables but did not help.
Suggest some ways which can increase the performance with only param10.
Try creating an index on REVDET.HCPCSRATES and then on snVwCodeXWalk.SOURCECODE. Try one first, then the other, then both, and see what effect it has.

selecting random records inside a UDF

I'm writing a function in sql server 2012.
I came to know that we can not use RAND() or NEWID() functions in the select statement of a function in sql server.
My function goes like this:
CREATE FUNCTION Keywordsuggester (#userid INT)
returns #suggestor_tab TABLE (
keywordid INT,
keywordname VARCHAR(max),
keywordcategory VARCHAR(max))
AS
BEGIN
DECLARE #category_table TABLE
(
category_name VARCHAR(max),
category_id INT,
rownum INT
)
DECLARE #ID INT = 1
DECLARE #COUNT INT = 0
DECLARE #I INT = 1
INSERT INTO #category_table
SELECT kc.NAME,
kc.id,
k.NAME,
d.NAME,
Row_number()
OVER(
ORDER BY d.id ASC) AS rownum
FROM dtypes d
JOIN keywords k
ON d.NAME LIKE '%' + k.NAME + '%'
JOIN keywordscategory kc
ON k.categoryid = kc.id
WHERE d.userid = #userid
SELECT #count = rownum
FROM #category_table
WHILE #count > #I
BEGIN
INSERT INTO #suggestor_tab
SELECT TOP 5 kc.id,
k.NAME,
kc.NAME
FROM kwords k
JOIN #category_table ct
ON k.categoryid = ct.category_id
JOIN kwcategory kc
ON kc.NAME = ct.category_name
WHERE ct.rownum = #I
--Here I'm inserting top 5 records for each category into the suggestor_tab,instead I have to insert random 5 records for each category(i.e.,#I)
SET #I=#I + 1
--return
END
INSERT INTO #suggestor_tab
SELECT kc.id,
k.NAME,
kc.NAME
FROM kwords k
JOIN #category_table ct
ON k.categoryid = ct.category_id
JOIN kwcategory kc
ON kc.NAME = category_name
RETURN
END
How can I get random records for each category(i.e., #I in the while loop).
I tried the query like:
SELECT TOP 5 k.NAME
FROM kwords k
JOIN #category_table ct
ON k.category_id = ct.id
JOIN kwcategory kc
ON kc.NAME = category_name
WHERE ct.rownum = #I
ORDER BY Newid()
which throws an error like:
Invalid use of a side-effecting operator 'newid' within a function.
Is there anyway to do this?
Thanks in advance.
You cannot use Non-deterministic Funcions inside UDF.
Create a View and use it in order by
create view Random
as
select newid() as New_id
Change you select something like this.
SELECT TOP 5 k.NAME
FROM KWords k
JOIN #category_table ct
ON k.category_id = ct.id
JOIN kwcategory kc
ON kc.NAME = category_name
WHERE ct.rownum = #I
ORDER BY (SELECT new_id
FROM random)

Resources