fastest update with sql - sql

I have the following query that it took days to be executed
DECLARE #cnt BIGINT
SET #cnt = 1
WHILE #cnt * 1000 < 92746339
BEGIN
UPDATE TOP (1000) [dbo].[Vente]
SET Promo =
CASE
WHEN [Code Article] IN (
SELECT [Code Article]
FROM [Promotion]
WHERE datecol BETWEEN [Date Debut Promo] AND [Date Fin Promo]
)
THEN 1
ELSE 0
END
WHERE promo IS NULL
PRINT '#cnt: ' + CONVERT(VARCHAR, #cnt)
SET #cnt = #cnt + 1
END
Number of rows : Vente = 92 millions and promotion =419187
The execution plan :
How to make it faster ?

Why not using a JOIN instead IN clause ?
UPDATE v
SET v.Promo = CASE
WHEN p.[Code Article] IS NOT NULL THEN 1
ELSE 0
END
FROM [dbo].[Vente] v
LEFT JOIN [Promotion] p
ON v.[Code Article] = p.[Code Article]
AND (datecol between [Date Debut Promo] AND [Date Fin Promo])
WHERE v.Promo IS NULL;
How many rows in your tables ?

Related

Best performance for paging query when using multiple statements in sql?

It is a bit complicated query but let me elaborate,
i have got multiple filter parameters in my procedure,
also a view named Vw1 and its regarded my main object in query that most of the filter parameters are filtered against this view that is located in another server,then i need to compare this view to another table and check two sides columns for possible conflict and then check if there is any conflict.
you can see my query below
ALTER PROC [dbo].[spGetAyandehVagozariWithConflict]
#Take INT,
#Skip INT,
#FromVagozariDate NVARCHAR(10),
#ToVagozariDate NVARCHAR(10),
#OrderBankCode NVARCHAR(4)=null,
#OrderBrCode NVARCHAR(7)=null,
#BenefBrCode NVARCHAR(4)=null,
#FromAmount NVARCHAR(50)=null,
#ToAmount NVARCHAR(50)=null,
#CheqSerie NVARCHAR(50)=null,
#CheqSerial NVARCHAR(10)=null,
#CheqStatus NVARCHAR(4)=null,
#CreditorNationalCode VARCHAR(20)=NULL,
#CheqType NVARCHAR(4)=null,
#BenefAccn NVARCHAR(13)=null,
#FromMatDate NVARCHAR(10)=null,
#ToMatDate NVARCHAR(10)=null,
#FromTaeenVaziatDate NVARCHAR(10)=null,
#ToTaeenVaziatDate NVARCHAR(10)=NULL,
#HasConflict VARCHAR(4)=null,
#TotalCnt INT OUTPUT,
#SUM BIGINT OUTPUT
AS
BEGIN
DECLARE #Query NVARCHAR(MAX)=''
IF(NULLIF(#FromVagozariDate,'') IS null)
SET #FromVagozariDate='NULL'
IF(NULLIF(#ToVagozariDate,'') IS null)
SET #ToVagozariDate='NULL'
IF(NULLIF(#OrderBrCode,'') IS null)
SET #OrderBrCode='NULL'
IF(NULLIF(#OrderBankCode,'') IS null)
SET #OrderBankCode='NULL'
IF(NULLIF(#BenefBrCode,'') IS null)
SET #BenefBrCode='NULL'
IF(NULLIF(#FromAmount,'') IS null)
SET #FromAmount='NULL'
IF(NULLIF(#ToAmount,'') IS null)
SET #ToAmount='NULL'
IF(NULLIF(#CheqSerie,'') IS null)
SET #CheqSerie='NULL'
IF(NULLIF(#CheqSerial,'') IS null)
SET #CheqSerial='NULL'
IF(NULLIF(#CheqStatus,'') IS null)
SET #CheqStatus='NULL'
IF(NULLIF(#CheqType,'') IS null)
SET #CheqType='NULL'
IF(NULLIF(#BenefAccn,'') IS null)
SET #BenefAccn='NULL'
IF(NULLIF(#ToMatDate,'') IS null)
SET #ToMatDate='NULL'
IF(NULLIF(#FromMatDate,'') IS null)
SET #FromMatDate='NULL'
IF(NULLIF(#FromTaeenVaziatDate,'') IS null)
SET #FromTaeenVaziatDate='NULL'
IF(NULLIF(#ToTaeenVaziatDate,'') IS null)
SET #ToTaeenVaziatDate='NULL'
IF(NULLIF(#HasConflict,'') IS null)
SET #HasConflict='NULL'
IF(NULLIF(#CreditorNationalCode,'') IS null)
SET #CreditorNationalCode='NULL'
IF #FromVagozariDate<>'NULL'
BEGIN
SET #FromVagozariDate=REPLACE(#FromVagozariDate,'/','')
END
IF #ToVagozariDate<>'NULL'
BEGIN
SET #ToVagozariDate=REPLACE(#ToVagozariDate,'/','')
END
IF #FromMatDate<>'NULL'
BEGIN
SET #FromMatDate=REPLACE(#FromMatDate,'/','')
END
IF #ToMatDate<>'NULL'
BEGIN
SET #ToMatDate=REPLACE(#ToMatDate,'/','')
END
IF #FromTaeenVaziatDate<>'NULL'
BEGIN
SET #FromTaeenVaziatDate=REPLACE(#FromTaeenVaziatDate,'/','')
SET #FromTaeenVaziatDate=SUBSTRING(#FromTaeenVaziatDate,3,6)
END
IF #ToTaeenVaziatDate<>'NULL'
BEGIN
SET #ToTaeenVaziatDate=REPLACE(#ToTaeenVaziatDate,'/','')
SET #ToTaeenVaziatDate=SUBSTRING(#ToTaeenVaziatDate,3,6)
END
IF #OrderBankCode<>'NULL'
BEGIN
--SET #OrderBankCode='0'+#OrderBankCode;
SET #OrderBankCode=dbo.LeftPad(#OrderBankCode,'0',3)
END
IF(#BenefBrCode<>'NULL')
BEGIN
SET #BenefBrCode=dbo.LeftPad(#BenefBrCode,'0',4)
END
IF(#OrderBrCode<>'NULL')
BEGIN
SET #OrderBrCode=dbo.LeftPad(#OrderBrCode,'0',4)
END
SET #Query=#Query+N'
SELECT *
INTO #Vw1
FROM [LinkedServer].DbName.dbo.Vw1 vd
where (vd.mat_date BETWEEN '+''''+#FromMatDate+''''+' AND'+''''+ #ToMatDate+''''+' OR ('+''''+#FromMatDate+''''+' =''NULL'' AND '+''''+#ToMatDate+''''+' =''NULL'' )) AND
(dbo.LeftPad(vd.order_bank_code,''0'',3)= '+''''+#OrderBankCode+''''+' OR '+''''+#OrderBankCode+''''+' =''NULL'') AND
(dbo.LeftPad(vd.order_brcode,''0'',4)= '+''''+#OrderBrCode+''''+' OR '+''''+#OrderBrCode+''''+' =''NULL'') AND
(dbo.LeftPad(vd.Benef_br_code,''0'',4)= '+''''+#BenefBrCode+''''+' OR '+''''+#BenefBrCode+''''+' =''NULL'') AND
(substring(vd.amount, patindex(''%[^0]%'',vd.amount), 10) BETWEEN '+''''+#FromAmount+''''+' AND '+''''+#ToAmount+''''+' OR ('+''''+#FromAmount+''''+' =''NULL'' AND '+''''+#ToAmount+''''+' =''NULL'')) AND
(RTRIM(LTRIM(vd.chq_serie))= '+''''+#CheqSerie+''''+' OR '+''''+#CheqSerie+''''+' =''NULL'') AND
(RTRIM(LTRIM(vd.chq_serial))= '+''''+#CheqSerial+''''+' OR '+''''+#CheqSerial+''''+' =''NULL'') AND
(vd.Chq_stat= '+''''+#CheqStatus+''''+' OR '+''''+#CheqStatus+''''+' in (''NULL'',''-1'')) AND
(vd.chq_type= '+''''+#CheqType+''''+' OR '+''''+#CheqType+''''+' =''NULL'') AND
(vd.benef_acno= '+''''+#BenefAccn+''''+' OR '+''''+#BenefAccn+''''+' =''NULL'') AND
((vd.taeen_vaziat_date is null AND ('+''''+#CheqStatus+''''+'=''-1'')) or('+''''+#CheqStatus+''''+'<>''-1'') ) AND
(vd.vagozari_date BETWEEN '+''''+#FromVagozariDate+''''+' AND '+''''+#ToVagozariDate+''''+' OR ('+''''+#FromVagozariDate+''''+' =''NULL'' AND '+''''+#ToVagozariDate+''''+' =''NULL'')) AND
(vd.taeen_vaziat_date BETWEEN '+''''+#FromTaeenVaziatDate+''''+' AND '+''''+#ToTaeenVaziatDate+''''+' OR ('+''''+#ToTaeenVaziatDate+''''+' =''NULL'' AND '+''''+#FromTaeenVaziatDate+''''+' =''NULL''))
order by system_no
select distinct cast(benef_acno as bigint) benef_acno
into #acno
from #Vw1
select ACNO,CUSTNO
into #ACTINFO
from [LinkServer1].[Db1].[dbo].[ACTINFO] af
where accno_id in (select * from #acno)
select [ECONOMIC-CODE],CUSTNO,FIRSTNAME +'' ''+LASTNAME CUSTNAME
into #CUSTINFO
from [LinkServer1].[Db1].[dbo].[CUSTINFO]
where CustNo_Id in (select cast(CUSTNO as bigint) from #ACTINFO)
SELECT
vd.*,
ct.Title CheqTypeTitle,
af.CUSTNO,cf.CUSTNAME,
--'''' as CUSTNO,'''' CUSTNAME,
cs.Status CheqStatusTitle,
av.Id AyandehVagozariId,
p.ParticipantName BenefBankName,
CASE WHEN ISNULL(vd.vagozari_date,'''') <> COALESCE(REPLACE(av.VagozariDate,''/'',''''),vd.vagozari_date,'''') THEN 1 ELSE 0 END VagozariDateHasConflict,
CASE WHEN ISNULL(dbo.LeftPad(vd.order_bank_code,''0'',3),'''') <> COALESCE(av.Order_Bank_Code,dbo.LeftPad(vd.order_bank_code,''0'',3),'''') THEN 1 ELSE 0 END OrderBankCodeHasConflict,
CASE WHEN ISNULL(dbo.LeftPad(vd.order_brcode,''0'',4),'''') <> COALESCE(av.Order_brCode,dbo.LeftPad(vd.order_brcode,''0'',4),'''') THEN 1 ELSE 0 END OrderBrCodeHasConflict,
CASE WHEN ISNULL(dbo.LeftPad(vd.Benef_br_code,''0'',4),'''') <> COALESCE(av.Benef_Br_Code,dbo.LeftPad(vd.Benef_br_code,''0'',4),'''') THEN 1 ELSE 0 END BenefBrCodeHasConflict,
CASE WHEN ISNULL(substring(vd.amount, patindex(''%[^0]%'',vd.amount), 10),'''') <> COALESCE(av.Amount,substring(vd.amount, patindex(''%[^0]%'',vd.amount), 10),'''') THEN 1 ELSE 0 END AmountHasConflict,
CASE WHEN ISNULL(vd.chq_serie,'''') <> COALESCE(av.Chq_serie,vd.chq_serie,'''') THEN 1 ELSE 0 END CheqSerieHasConflict,
CASE WHEN ISNULL(RTRIM(LTRIM(vd.chq_serial)),'''') <> COALESCE(av.Chq_Serial,RTRIM(LTRIM(vd.chq_serial)),'''') THEN 1 ELSE 0 END CheqSerialHasConflict,
CASE WHEN ISNULL(vd.chq_type,'''') <> COALESCE(av.Chq_Type,vd.chq_type,'''') THEN 1 ELSE 0 END CheqTypeHasConflict,
CASE WHEN ISNULL(vd.benef_acno,'''') <> COALESCE(av.Benef_Acno,vd.benef_acno,'''') THEN 1 ELSE 0 END BenefAcnoHasConflict,
CASE WHEN ISNULL(vd.mat_date,'''') <> COALESCE(REPLACE(av.Mat_Date,''/'',''''),vd.mat_date,'''') THEN 1 ELSE 0 END MatDateHasConflict,
CASE WHEN ISNULL(cf.CUSTNO,'''') <> COALESCE(av.CUSTNO,cf.CUSTNO COLLATE DATABASE_DEFAULT,'''') THEN 1 ELSE 0 END CustNoHasConflict,
--CASE WHEN ISNULL(vd.taeen_vaziat_date,'''') <> COALESCE(av.Taeen_Vaziat_Date,vd.taeen_vaziat_date,'''') THEN 1 ELSE 0 END TaeenVaziatDateHasConflict,
0 as TaeenVaziatDateHasConflict,
CASE WHEN ISNULL(vd.Chq_stat,'''') <> COALESCE(av.Chq_Status,vd.Chq_stat,'''') THEN 1 ELSE 0 END CheqStatusHasConflict
--0 as VagozariDateHasConflict,
--0 as OrderBankCodeHasConflict,
--0 as OrderBrCodeHasConflict,
--0 as BenefBrCodeHasConflict,
--0 as AmountHasConflict,
--0 as CheqSerieHasConflict,
--0 as CheqSerialHasConflict,
--0 as CheqTypeHasConflict,
--0 as BenefAcnoHasConflict,
--0 as MatDateHasConflict,
--0 as TaeenVaziatDateHasConflict
INTO #temp
FROM #vw_faranam_vagozari_chakavak vd
LEFT JOIN #ACTINFO af on vd.benef_acno=af.ACNO COLLATE Arabic_CI_AS
LEFT JOIN #CUSTINFO cf on af.CUSTNO=cf.CUSTNO COLLATE Arabic_CI_AS
LEFT JOIN [AyandehVagozari] av ON av.SystemNo=vd.system_no
LEFT JOIN [Cheque_Type_Biha] ct ON ct.Code=vd.chq_type
LEFT JOIN [ChequeStatusForBiha] cs ON cs.Id=vd.Chq_stat
LEFT JOIN [Participant] p ON ''0''+p.ParticipantCode=vd.order_bank_code
WHERE (cf.[ECONOMIC-CODE]= '+''''+#CreditorNationalCode+''''+' OR '+''''+#CreditorNationalCode+''''+' =''NULL'')
order by vd.system_no
DELETE t FROM(
SELECT *,ROW_NUMBER() OVER(partition by system_no order by AyandehVagozariId desc) rn FROM
#temp
)t
where rn>1
SELECT *,
case when (VagozariDateHasConflict=1 or OrderBankCodeHasConflict=1 or OrderBrCodeHasConflict =1 OR BenefBrCodeHasConflict=1
or AmountHasConflict=1 or CheqSerieHasConflict=1 or CheqSerialHasConflict=1 or CustNoHasConflict=1
or CheqStatusHasConflict=1 or CheqTypeHasConflict=1 or BenefAcnoHasConflict=1 or MatDateHasConflict=1 or TaeenVaziatDateHasConflict=1)
then 1 else 0 end HasConflict
INTO #TmpResult
FROM #temp
order by system_no
--here is where i filter my last parameter but it seems too late..because alot of records already involved !
SELECT *,ROW_NUMBER() over (ORDER BY system_no) RowNumber
into #finalTemp
FROM
#TmpResult
where (HasConflict=1 and '+''''+#HasConflict+''''+'=''1'')
OR (HasConflict=0 and '+''''+#HasConflict+''''+'=''0'')
OR ('+''''+#HasConflict+''''+'=''NULL'')
order by system_no
SELECT #Total=##ROWCOUNT
select #Sum=isnull(SUM(cast(amount as bigint)),0) from
#finalTemp
select * from
#finalTemp
WHERE RowNumber >'+CAST(#Skip AS NVARCHAR(10))+' AND RowNumber<=('+CAST(#Skip+#Take AS NVARCHAR(10))+')
'
PRINT #Query
EXEC sp_executesql #Query,N'#Total int output,#Sum bigint output',#TotalCnt OUTPUT,#SUM OUTPUT
END
due to performance issues i had to write it in dynamic way,But the problem is that i could not wrap my head around paging in this query, bacause as you see i should put paging line in the end of query because #HasConflict parameters exist and i cannot check it earlier,and in this way my paging seems pointless because i'm dealing with huge load of data ...
also i cannot use offset for paging because my sql version is too old ...

How to update table based on the values in other columns

Here is a sample below, I want to update AvailableAmt column based on the amount entered on UI.
Requirement
Update the value from the last row to the first row,
If entered 500 on UI, then the table will be like
If entered 1000 on UI, then the table will be like
Thank you for your help in advance !
Can't test it on a Sybase somewhere.
But in theory something like this might work:
DECLARE #Group VARCHAR(8) = 'a';
DECLARE #Amount INT = 1100;
UPDATE t
SET t.AvailableAmt =
CASE
WHEN q.PrevRemain > 0 AND t.AvailableAmt <= q.PrevRemain THEN 0
WHEN q.PrevRemain > 0 THEN t.AvailableAmt - q.PrevRemain
ELSE t.AvailableAmt
END
FROM YourTable t
JOIN
(
select [Group], [Row],
#Amount-(SUM(AvailableAmt) OVER (PARTITION BY [Group] ORDER BY AvailableAmt, [Row] desc) - AvailableAmt) as PrevRemain
from YourTable
where AvailableAmt > 0
and [Group] = #Group
) AS q
ON (q.[Group] = t.[Group] and q.[Row] = t.[Row]);
For a Sybase flavor that doesn't support the window function of SUM, something like this might work.
DECLARE #Group VARCHAR(8) = 'a';
DECLARE #Amount INT = 1200;
UPDATE t
SET t.AvailableAmt =
CASE
WHEN q.PrevRemain > 0 AND t.AvailableAmt <= q.PrevRemain THEN 0
WHEN q.PrevRemain > 0 THEN t.AvailableAmt - q.PrevRemain
ELSE t.AvailableAmt
END
FROM YourTable t
JOIN
(
select t1.[Group], t1.[Row],
#Amount - (SUM(t2.AvailableAmt)-t1.AvailableAmt) as PrevRemain
from YourTable t1
left join YourTable t2 on (t2.[Group] = t1.[Group] and t2.AvailableAmt <= t1.AvailableAmt and t2.[Row] >= t1.[Row])
where t1.AvailableAmt > 0
and t1.[Group] = #Group
group by t1.[Group], t1.[Row], t1.AvailableAmt
) AS q
ON (q.[Group] = t.[Group] and q.[Row] = t.[Row]);

SQL: LEFT OUTER JOIN not returning any rows

I have a query that is using a LEFT OUTER JOIN to merge 2 data sets. I know both data sets should return data because I ran the superquery and the subquery separately. For some reason, the query is returning zero results. Anyone know why?
Left data:
item FG_lots
447845 E2211
Right data:
candy_lot_check candy_item
L2211 835116
Intended result:
item FG_lots candy_lot_check candy_item
447845 E2211 null null
The result from my broken query (no results):
item FG_lots candy_lot_check candy_item
The query:
--Initialization--
DECLARE #Item NVARCHAR(30) = '447845'
DECLARE #Date datetime = '6/13/2016'
SET DATEFIRST 1;
DECLARE #client NVARCHAR(20)
SET #client = (SELECT i.Uf_ClientName FROM item AS i WHERE i.item = #Item)
DECLARE #count integer
--Query--
SET #count = (CASE
WHEN (#client = 'A' OR #client = 'B')
THEN 4
WHEN #client = 'C'
THEN 3
WHEN #client = 'D'
THEN 5
ELSE
4
END)
SELECT DISTINCT
t.item,
LEFT(t.lot,#count) AS FG_lots,
(CASE
WHEN candylot.candy_lots IS NULL
THEN 'NO MATCH'
ELSE candylot.candy_lots
END) AS candy_lot_check,
(CASE
WHEN candylot.item IS NULL
THEN 'NO MATCH'
ELSE candylot.item
END) AS candy_item
FROM
ISW_LPTrans AS t
LEFT OUTER JOIN
(
SELECT
t.item,
LEFT(t.lot,#count) AS candy_lots,
t.ref_num AS job,
t.ref_line_suf AS suffix
FROM
ISW_LPTrans AS t
INNER JOIN item AS i on i.item = t.item
WHERE
i.product_code = 'RM-Candy' AND
t.trans_date = #Date AND
t.trans_type = 'I' AND
t.ref_num IN
(
SELECT TOP 1
j.job
FROM
job AS j
WHERE
j.item = #Item AND
j.job_date = (SELECT DATEADD(DAY, 1-DATEPART(WEEKDAY, #Date), #Date))
ORDER BY
j.job
)
AND t.ref_line_suf IN
(
SELECT TOP 1
j.suffix
FROM
job AS j
WHERE
j.item = #Item AND
j.job_date = (SELECT DATEADD(DAY, 1-DATEPART(WEEKDAY, #Date), #Date))
)
GROUP BY
t.item,
t.lot,
t.ref_num,
t.ref_line_suf
) AS candylot ON LEFT(t.lot, #count) = candylot.candy_lots
WHERE
t.ref_num = candylot.job AND
t.ref_line_suf = candylot.suffix AND
t.trans_type = 'F' AND
t.item = #Item AND
t.trans_date = #Date
You've got two 't' aliases, try altering it.
It seems you could rewrite it to make it more readable (joinwise, not indentwise), it could be that something's not right in the logic as well

Less expensive query?

I have a stored procedure that returns an integer 1 or 0 depending on specific criteria. It currently uses three select statements and it will be used heavily by multiple users across multiple locations. There has to be a more efficient way of doing this.
In short the query checks first to see if all checklist items on an order are completed (a separate table), then it checks to see if a field named BreakOutGuest (a bit field) is a 1 or 0. Depending on that result it checks to see if the total guest count is greater than 0 and the order total is zero. It returns the one or zero on all this criteria. Is there a more efficient way to do this? A temp table so I only have to hit the actual tables once? Below is the code.
#ORDERID INT
AS
BEGIN
DECLARE #AUTO_CLOSE INT
SET NOCOUNT ON;
--If all checklist items are marked complete move on, if not set #AUTO_CLOSE=0
IF NOT EXISTS(SELECT ORDERID FROM dbo.orderchecklistitems WHERE OrderID=#ORDERID AND CompletedON IS NULL)
BEGIN
--if BreakOutGuestFees is 1 only sum Guest_Count_1 + Guest_Count_2
IF EXISTS(SELECT * FROM dbo.Orders WHERE (GuestCount_1 + GuestCount_2)>1 AND OrderTotal=0 AND BreakoutGuestFees=1)
BEGIN
SET #AUTO_CLOSE=1
END
ELSE
SET #AUTO_CLOSE=0
--if BreakOutGuestFees is 0 only consider Guest_Count_1
IF EXISTS(SELECT * FROM dbo.Orders WHERE (GuestCount_1)>1 AND OrderTotal=0 AND BreakoutGuestFees=0)
BEGIN
SET #AUTO_CLOSE=1
END
ELSE
SET #AUTO_CLOSE=0
END
ELSE
SET #AUTO_CLOSE=0
END
If am not wrong you can combine two if clause into single if clause by using AND , OR logic. Try this.
IF NOT EXISTS(SELECT ORDERID
FROM dbo.orderchecklistitems
WHERE OrderID = #ORDERID
AND CompletedON IS NULL)
BEGIN
IF EXISTS(SELECT *
FROM dbo.Orders
WHERE ( ( GuestCount_1 + GuestCount_2 > 1
AND BreakoutGuestFees = 1 )
OR ( BreakoutGuestFees = 0
AND GuestCount_1 > 1 ) )
AND OrderTotal = 0
AND OrderID = #ORDERID)
SET #AUTO_CLOSE=1
ELSE
SET #AUTO_CLOSE=0
END
ELSE
SET #AUTO_CLOSE=0
You can perform your selection check with only one query
SELECT
(SELECT sum(1) FROM dual WHERE EXISTS (SELECT ORDERID FROM dbo.orderchecklistitems WHERE OrderID=#ORDERID AND CompletedON IS NULL)),
(SELECT sum(1) FROM dual WHERE EXISTS (SELECT 1 FROM dbo.Orders WHERE (GuestCount_1 + GuestCount_2)>1 AND OrderTotal=0 AND BreakoutGuestFees=1)),
(SELECT sum(1) FROM dual WHERE EXISTS (SELECT 1 FROM dbo.Orders WHERE (GuestCount_1)>1 AND OrderTotal=0 AND BreakoutGuestFees=0))
INTO
result1, result2, result3
from dual
then check results
DELCARE #AUTO_CLOSE INT = 0
IF NOT EXISTS(SELECT ORDERID
FROM dbo.orderchecklistitems
WHERE OrderID = #ORDERID
AND CompletedON IS NULL)
BEGIN
SET #AUTO_CLOSE =
(
SELECT
CASE
WHEN (GuestCount_1 + GuestCount_2 > 1) AND BreakoutGuestFees = 0 THEN 1
WHEN (GuestCount_1 > 1 ) AND BreakoutGuestFees = 1 THEN 1
ELSE 0 END
FROM dbo.orders
WHERE OrderTotal = 0 AND OrderID = #orderID
)
END

Unable to get the required result using update statement

I am unable to update the data using record by record below scenario.
Required output: patient will able to Admit/Re-admit multiple times in hospital, if a patient readmitted multiple times in hospital after the first visit, first visit record will get Re-admission=0 and Index=1. This visit should cal Index_Admission of that patient. using this index_admission should calculate the 30-day readmission.
Current Output:
Calculation:
From index_admission discharge date to next admit_visit date,
1) if the diff is having less than 30 days, readmission=1 and Index=0
else readmission=0 and Index=1 should be update.
For checking this every time should check using the latest index_admission discharge_date.
To get this result i written below logic, but it's updating readmission=0 and Index=1 after 30-day post discharge of using first index admission.
UPDATE Readmission
SET Index_AMI = (CASE
WHEN DATEDIFF(DD, (SELECT
Sub.Max_Index_Dis
FROM (SELECT
Patient_ID,
MAX(Discharge_Date_Time) Max_Index_Dis
FROM Readmission
WHERE Index_AMI = 1 AND FPR.Patient_ID = Patient_ID
GROUP BY Patient_ID) Sub), FPR.Admit_Date_Time) <= 31 THEN 0 ELSE 1
END),
Is_AMI_Readmission = (CASE
WHEN DATEDIFF(DD, (SELECT
Sub.Max_Index_Dis
FROM (SELECT
Patient_ID,
MAX(Discharge_Date_Time) Max_Index_Dis
FROM Readmission
WHERE Index_AMI = 1 AND FPR.Patient_ID = Patient_ID
GROUP BY Patient_ID) Sub)
, FPR.Admit_Date_Time) <= 31 THEN 1 ELSE 0
END)
FROM Readmission FPR
WHERE fpr.index_ami IS NULL
Expected Result:
Please help me to resolve the issue.
Best Regards,
Nagendra
Thank you all for trying to help.
I some how managed to solve it using temporary tables.
If there is any issues, especially performance, with this approach please feel free to comment/criticize.
/*------------ To moving all Patient_Readmission data into temp table -------------*/
IF EXISTS (select * FROM tempdb.dbo.sysobjects o
WHERE o.xtype IN ('U')
AND o.id = OBJECT_ID(N'tempdb..#Readmission')
)
Begin
DROP TABLE #Readmission
End
IF NOT EXISTS (SELECT * FROM tempdb.dbo.sysobjects o
WHERE o.xtype IN ('U')
AND o.id = OBJECT_ID(N'tempdb..#Readmission')
)
BEGIN
select Patient_ID,ID,Encounter_Code
,Admit_Date_Time,Discharge_Date_Time
,Is_AMI_Readmission,Index_AMI
into #Readmission
from Patient_Readmission
END
GO
/*----------- To get Max Index discharge_date for all patients where index=1----------*/
IF EXISTS (select * FROM tempdb.dbo.sysobjects o
WHERE o.xtype IN ('U')
AND o.id = OBJECT_ID(N'tempdb..#Each_Pt_Max_Dsrg')
)
Begin
DROP TABLE #Each_Pt_Max_Dsrg
End
IF NOT EXISTS (SELECT * FROM tempdb.dbo.sysobjects o
WHERE o.xtype IN ('U')
AND o.id = OBJECT_ID(N'tempdb..#Each_Pt_Max_Dsrg')
)
BEGIN
select Patient_ID,Index_AMI,Max(Discharge_Date_Time) Max_Index_Dis
into #Each_Pt_Max_Dsrg
from #Readmission where Index_AMI=1 group by Patient_ID,Index_AMI
END
Declare #var int
Set #var=(select Min(Patient_ID) from #Each_Pt_Max_Dsrg)
While #var is not null
Begin
Declare #Var_En int
declare #maxDisch datetime
Set #Var_En=(Select Min(ID) From #Readmission Where Index_AMI Is null and Patient_ID=#var)
While #Var_En is Not NULL
Begin
set #maxDisch = dateadd(dd,-1,(select max(Max_Index_Dis) from #Each_Pt_Max_Dsrg where Index_AMI=1 and Patient_ID=#var))
while (#maxDisch < (select max(Max_Index_Dis) from #Each_Pt_Max_Dsrg where Index_AMI=1 and Patient_ID=#var))
begin
Update #Readmission
set Index_AMI=(Case When Datediff(DD,(Select Max(Max_Index_Dis) From #Each_Pt_Max_Dsrg Where Index_AMI=1 And Patient_ID=#var),FPR.Admit_Date_Time) between 0 and 31 Then 0 Else 1 End)
,Is_AMI_Readmission=(Case When Datediff(DD,(Select Max(Max_Index_Dis) From #Each_Pt_Max_Dsrg Where Index_AMI=1 And Patient_ID=#var),FPR.Admit_Date_Time) between 0 and 31 Then 1 Else 0 End)
From #Readmission FPR where Patient_ID=#var and ID=#Var_En and Index_AMI is NULL
set #maxDisch = (select max(Max_Index_Dis) from #Each_Pt_Max_Dsrg where Index_AMI=1 and Patient_ID=#var)
delete from #Each_Pt_Max_Dsrg
insert into #Each_Pt_Max_Dsrg
select Patient_ID,Index_AMI,Max(Discharge_Date_Time) Max_Index_Dis
from #Readmission where Index_AMI=1 group by Patient_ID,Index_AMI
end
SET #Var_En = (SELECT Min(ID) FROM #Readmission WHERE ID> #Var_En)
End
SET #Var = (SELECT MIN(Patient_ID) FROM #Each_Pt_Max_Dsrg WHERE Patient_ID > #var)
End