Add the correct condition in WHERE statement using CASE - sql-server

It's been months since I explore SQL Server but I am still new to this field. I need to output rows that will return ISBLANK = 0 or ISBLANK IS NULL. I am using CASE statement.
Expected output:
My code:
SELECT UD.FID
, UD.UID
, CBH.BID
, FBA.ISBLANK
FROM TEMP_UD UD
INNER JOIN TBL_CBH CBH
ON UD.FID = CBH.FID
INNER JOIN TBL_UDF UDF
ON UDF.FID = UDF.FID
LEFT JOIN TBL_FBA FBA
ON FBA.FID = CBH.FID
AND FBA.BID = CBH.BID
WHERE
(
CASE
WHEN UDF.COND = 10 AND UDF.UID = 12 AND FBA.ISBLANK != 1
THEN 0
END = FBA.ISBLANK
)
Current output:
FID UID BID ISBLANK
-------------------
1 12 1 0
1 12 1 0
Sample code:
https://onecompiler.com/mysql/3y29djktg

Try:
CASE WHEN UDF.COND = 10
AND UDF.UID = 12
AND FBA.ISBLANK = 1
THEN 1
ELSE 0
END = 1
This will/should return the rows where ISBLANK 1 1 does not apply.
I am wondering why you are not using the conditions directly in the WHERE, like this:
WHERE UDF.COND = 10
AND UDF.UID = 12
AND ( FBA.ISBLANK IS NULL OR FBA.ISBLANK = 0 )
If any optimizations can be made based on the columns that are used, they cannot be made if they are used in a CASE expression.

Related

Updating one column based on parameter from another column in mssl1

Please I want to update my client database based on the job type
id Job_type Meal_Ticket
---------------------------
1 x 20
2 2x 12
Meaning if I click on add 20 meal tickets on button click, it should update to this:
id Job_type Meal_Ticket
----------------------------
1 x 40
2 2x 52
I tried
UPDATE Staff
SET Rticket = CASE
WHEN Jobtype = 'x' THEN Rticket = SUM(Rticket + 20)
WHEN Jobtype = '2x' THEN Rticket = SUM(Rticket + 2*20)
ELSE Rticket
END
I think you want this:
UPDATE Staff
SET Rticket = CASE WHEN Jobtype = 'x' THEN Rticket + 20
WHEN Jobtype = '2x' THEN Rticket + 40 END
WHERE Jobtype IN ('x', '2x');
The only problem I see with your logic is that you are using SUM to add two quantities, when you should just be using the + operator.

What is optimal number of tables we can use with JOINs?

I have a query which fetches records from 7 tables. All these tables are JOINed to get the details, few tables used multiple times with different ON clause. So there are 10 JOINs in the query. How can we optimize the query for getting better performance? We already have indexes on JOIN columns. Anything we can do to reduce the number of JOINs? Am using MS SQL 2012 with compatibility level 2008.
Query:
SELECT TOP 100
MT.ProjectId,
matRef,
matDescription,
matKeyDescription,
matOpenDate,
matUFN,
matBranchRef,
matClosedDate,
ERN1.feeRef,
WorkTypeCode,
DPT.deptNo AS matDeptRef,
PreviousRef,
MT.ApplicationID,
MatterCompleted,
CASE WHEN MLC.PFCivil_MatterCount = 0 THEN 0 ELSE 1 END AS IsCPF,
CASE WHEN MLC.PF_MatterCount = 0 THEN 0 ELSE 1 END AS IsPF,
CASE WHEN MLC.Family_MatterCount = 0 THEN 0 ELSE 1 END AS IsFM,
CASE WHEN MLC.WL_MatterCount = 0 THEN 0 ELSE 1 END AS IsWills,
CASE WHEN MLC.Convey_MatterCount = 0 THEN 0 ELSE 1 END AS IsConvey,
CASE WHEN MLC.Probate_MatterCount = 0 THEN 0 ELSE 1 END AS IsProbate,
CASE WHEN MLC.PI_MatterCount = 0 THEN 0 ELSE 1 END AS IsPi,
CASE WHEN MLC.PIPortal_MatterCount = 0 THEN 0 ELSE 1 END AS IsPiPortal,
CASE WHEN MLC.CM_MatterCount = 0 THEN 0 ELSE 1 END AS IsChest,
CASE WHEN MLC.Campaigns_MatterCount = 0 THEN 0 ELSE 1 END AS IsMarketing,
CASE WHEN MLC.PFFamilyFixedFee_MatterCount = 0 THEN 0 ELSE 1 END AS IsPFFamilyFixedFeeMatter,
ERN2.feeRef AS MatPartner,
MatPFCertificateNo,
CASE WHEN MT.matClosedDate = {d''1753-01-01''} THEN 0 ELSE 1 END AS IsArchived,
'''' Modules,
MT.ChargeDescID,
MT.MatterTypeID,
PrimaryClient.ClientName,
MB.LastAccDate,
MB.LastBillDate,
MB.LastClientDate,
MB.LastTimeDate
FROM dbo.Matter AS MT
JOIN dbo.Departments AS DPT ON DPT.deptID = MT.deptID
JOIN dbo.Earners AS ERN1 ON ERN1.MemberId = MT.MatFeeMemId
JOIN dbo.Earners AS ERN2 ON ERN2.MemberId = MT.matPartnerMemId
JOIN dbo.WorkTypes AS WT ON WT.WorkTypeID = MT.WorkTypeID
JOIN dbo.ivw_MatterLinkCount AS MLC ON MLC.ProjectId = MT.ProjectId
JOIN dbo.Banks AS ClientBank ON MT.matClientBank = ClientBank.bankID
JOIN dbo.Banks AS OfficeBank ON MT.matOfficeBank = OfficeBank.bankID
JOIN dbo.Banks AS DepositBank ON MT.matDepositBank = DepositBank.bankID
JOIN uvw_MatterPrimaryClient AS PrimaryClient ON PrimaryClient.ProjectId = MT.ProjectId
JOIN dbo.MatterBalance AS MB ON MT.ProjectId = MB.ProjectID
WHERE matDescription LIKE #Description
ORDER BY Isarchived, matRef
The trick here is that 'WHERE matDescription LIKE #Description' is not the real filter.
The real filter is 'TOP 100' together with 'ORDER BY Isarchived, matRef' because this filter will absolutely filter out anything but 100 rows.
So you need an index at Isarchived, matRef too. Table scan for matRef probably delays this one.
Also unless the Isarchived, matRef combination is unique by constraint, you better add the PK at the end like ORDER BY Isarchived, matRef, matid so there would be no extra problem picking the top 100.
Finally, if Isarchived is something like 0/1 and you have tons of records with 0 value it is useless at order by as there would always be 0. Set it as a filter Isarchived = 0 and remove it from order by - use matRef, matid and add a single index to matRef only.

What causing errors with this stored procedure?

I have a stored procedure to process monthly jobs. The stored procedure will loop through all the available jobs and do some calculation before it's inserted into a table. It was fine for most jobs but for some jobs, there will be an error
Subquery returned more than 1 value. This is not permitted when the
subquery follows =, !=, <, <= , >, >= or when the subquery is used as
an expression.
Below is the section where it says the error occurred:
IF EXISTS( SELECT *
FROM aastocks aastk
WHERE aastk.estno = #lcEstno
and 0 in (aastk.cartonratio1,
aastk.cartonratio2,
aastk.cartonratio3,
aastk.cartonratio4,
aastk.cartonratio5)
) EXECUTE ru_est_stocksum #lcEstNo
#lcEstNo was defined in the previous code.
SET #lcEstno = (SELECT MAX(estno) FROM dbo.v_est_joblist WHERE ljob = #tcLjob)
MAX() should return only 1 value and I don't understand why the multi value error.
Well, as it turns out, the line number of the error is not the same as the line number in the Stored Procedure. So the problem actually resides in the following code(After I comment out the below section and there is no error). But I am not able to find out which subquery is returning more than 1 value. Any idea ?
INSERT INTO #JCDTotals
SELECT #tcLjob, coalesce(cast( ap.deptno as char(4)),'????') as deptno,
CASE WHEN coalesce(v_depuse_qty.DepUse, 1) = 1 THEN
CASE WHEN #tcCostBase = 'D' THEN CASE WHEN ap.procgroup = 'I' THEN aaprocqt.dmcstmat1 + aaprocqt.dmcstmat2 + aaprocqt.dmcstmat3 END
WHEN #tcCostBase = 'A' THEN CASE WHEN ap.procgroup = 'I' THEN aaprocqt.costmats1 + aaprocqt.costmats2 + aaprocqt.costmats3 END
ELSE ' 0 '
END
ELSE 0 END AS ecostmats,
CASE WHEN coalesce(v_depuse_qty.DepUse, 1) = 1 THEN CASE WHEN #tcCostBase = 'D' THEN (1 / (1 + (ap.burden/100))) ELSE 1 END
* aaprocqt.costlab
ELSE 0
END AS ecostlab,
CASE WHEN coalesce(v_depuse_qty.DepUse, 1) = 1 THEN aaprocqt.proctime
ELSE 0
END AS eprochours,
0.0 AS bcostmats,
0.0 AS bcostlab,
0 AS bprochours,
0.0 AS acostmats,
0.0 AS acostlab,
0 AS aprochours,
0.0 AS chgcost,
0 AS dirlab,
0.0 AS aacost,
0.0 AS pecost,
0.0 AS otcost,
0 AS sell
FROM (
SELECT aaproces.idnumber,
aaproces.estno,
aaproces.procgroup,
aaproces.partno,
aaproces.[lineno],
aaproces.counter,
ssproces.burden,
case WHEN aaproces.procgroup = 'I' then ssinvent.deptno
else ssproces.deptno end as deptno,
case WHEN aaproces.procgroup = 'I' then ssinvent.matno
else STR(ssproces.procno,6) end as procno,
case WHEN aaproces.procgroup = 'I' then ssinvent.material
else ssproces.process end as process
FROM dbo.aaproces
LEFT JOIN dbo.SSINVENT ON ssinvent.matno = aaproces.matno
AND ssinvent.invtype IN ('G', 'I', 'F', 'S')
LEFT JOIN dbo.SSPROCES ON ssproces.procno = aaproces.procno
WHERE ((aaproces.procgroup = 'I' and ssinvent.deptno is not null)
OR (aaproces.procgroup <> 'I' and ssproces.deptno is not null))
AND ((aaproces.procgroup = 'I' and ssinvent.matno is not null)
OR (aaproces.procgroup <> 'I' and ssproces.procno is not null))
) ap
INNER join dbo.v_est_joblist
on v_est_joblist.estno = ap.estno
LEFT OUTER JOIN dbo.aaprocqt
on aaprocqt.estno = ap.estno
and ap.[lineno] = aaprocqt.[lineno]and aaprocqt.procgroup = ap.procgroup
and ap.partno = aaprocqt.partno and ap.counter = aaprocqt.counter and aaprocqt.qty = v_est_joblist.alt
LEFT OUTER JOIN dbo.v_depuse_qty
ON v_est_joblist.estno = v_depuse_qty.estno
AND v_depuse_qty.deptno = ap.deptno
AND V_DEPUSE_QTY.LJOB = V_EST_JOBLIST.LJOB
AND V_DEPUSE_QTY.ALT = V_EST_JOBLIST.ALT
WHERE v_est_joblist.ljob = #tcLjob
-- AND ssdept.divno like #lcDivNo
--------------------------------------------------------------------------- PROCESS MATERIAL1,MATERIAL2,MATERIAL3 (ESTIMATED)
UNION ALL
SELECT #tcLjob, coalesce(ssinvent.deptno,'????') as deptno,
CASE WHEN coalesce((SELECT v_depuse_qty.DepUse FROM dbo.v_depuse_qty WHERE v_est_joblist.estno = v_depuse_qty.estno
AND ssinvent.deptno = v_depuse_qty.deptno
AND V_DEPUSE_QTY.LJOB = V_EST_JOBLIST.LJOB
AND V_DEPUSE_QTY.ALT = V_EST_JOBLIST.ALT), 1) = 1 THEN CASE WHEN sq.CopyNum = 1 THEN CASE WHEN #tcCostBase = 'D' THEN aaprocqt.dmcstmat1 ELSE aaprocqt.costmats1 END
WHEN sq.CopyNum = 2 THEN CASE WHEN #tcCostBase = 'D' THEN aaprocqt.dmcstmat2 ELSE aaprocqt.costmats2 END
WHEN sq.CopyNum = 3 THEN CASE WHEN #tcCostBase = 'D' THEN aaprocqt.dmcstmat3 ELSE aaprocqt.costmats3 END
END
ELSE 0
END AS ecostmats,
0 AS ecostlab,
0 AS eprochours,
0 AS bcostmats,
0 AS bcostlab,
0 AS bprochours,
0.0 AS acostmats,
0.0 AS acostlab,
0 AS aprochours,
0.0 AS chgcost,
0 AS dirlab,
0.0 AS aacost,
0.0 AS pecost,
0.0 AS otcost,
0 AS sell
FROM dbo.aaproces JOIN dbo.v_est_joblist on v_est_joblist.estno = aaproces.estno
CROSS JOIN #NumCopies sq
LEFT JOIN dbo.ssproces on aaproces.procno = ssproces.procno
LEFT JOIN dbo.ssinvent on ssinvent.matno = ( case when sq.CopyNum = 1 then CASE WHEN aaproces.manmatno = '' THEN ssproces.matno1 ELSE aaproces.manmatno END
when sq.CopyNum = 2 then CASE WHEN aaproces.manmatno2 = '' THEN ssproces.matno2 ELSE aaproces.manmatno2 END
when sq.CopyNum = 3 then CASE WHEN aaproces.manmatno3 = '' THEN ssproces.matno3 ELSE aaproces.manmatno3 END
end)
JOIN dbo.aaprocqt on aaprocqt.estno = aaproces.estno and aaprocqt.procgroup = aaproces.procgroup
and aaproces.partno = aaprocqt.partno and aaproces.[lineno] = aaprocqt.[lineno]
and aaproces.counter = aaprocqt.counter and aaprocqt.qty = v_est_joblist.alt
WHERE aaproces.procgroup <> 'I'
--and sq.CopyNum < 4
and case when sq.CopyNum = 1 then (manmatno + matno1 )
when sq.CopyNum = 2 then (aaproces.manmatno2 + ssproces.matno2 )
when sq.CopyNum = 3 then (manmatno3 + matno3 )
end <> ''
AND v_est_joblist.ljob = #tcLjob
--------------------------------------------------------------------------- STOCKS (ESTIMATED)
UNION ALL
SELECT #tcLjob, coalesce(case when aastocks.houvend = 'H' then ssinvent.deptno
else case when aapthead.parttype = 'S' then #opt_stockccs
else #opt_stockccr end end,'????')
as deptno,
CASE WHEN coalesce((SELECT v_depuse_qty.DepUse FROM dbo.v_depuse_qty WHERE v_est_joblist.estno = v_depuse_qty.estno
AND v_depuse_qty.deptno = ssdept.deptno
AND V_DEPUSE_QTY.LJOB = V_EST_JOBLIST.LJOB
AND V_DEPUSE_QTY.ALT = V_EST_JOBLIST.ALT), 1) = 1 THEN CASE WHEN #tcCostBase = 'D' THEN
CASE WHEN aastocks.houvend = 'V' THEN (1 / (1 + (ssdept.burden/100)))
ELSE (1 / (1 + (ssinvent.burden/100))) END
ELSE 1 END *
case when v_est_joblist.alt = 1 then aastocks.stkcost1 * aastocks.cartonratio1
when v_est_joblist.alt = 2 then aastocks.stkcost2 * aastocks.cartonratio2
when v_est_joblist.alt = 3 then aastocks.stkcost3 * aastocks.cartonratio3
when v_est_joblist.alt = 4 then aastocks.stkcost4 * aastocks.cartonratio4
when v_est_joblist.alt = 5 then aastocks.stkcost5 * aastocks.cartonratio5
END
ELSE 0
END AS ecostmats,
0 as ecostlab,
0 as eprochours,
0 AS bcostmats,
0 AS bcostlab,
0 AS bprochours,
0.0 AS acostmats,
0.0 AS acostlab,
0 AS aprochours,
0.0 AS chgcost,
0 AS dirlab,
0.0 AS aacost,
0.0 AS pecost,
0.0 AS otcost,
0 AS sell
FROM dbo.aapthead
INNER JOIN dbo.aastocks on aapthead.estno = aastocks.estno and aapthead.partno = aastocks.partno
INNER JOIN dbo.v_est_joblist on v_est_joblist.estno = aapthead.estno
LEFT OUTER JOIN dbo.ssinvent on aastocks.matno = ssinvent.matno
AND ssinvent.invtype IN ('R', 'S')
LEFT OUTER JOIN dbo.ssdept ON ssdept.deptno = (CASE WHEN aastocks.houvend = 'H' THEN ssinvent.deptno
ELSE CASE WHEN aapthead.parttype = 'S' THEN #opt_stockccs
ELSE #opt_stockccr
END
END)
WHERE v_est_joblist.ljob = #tcLjob
AND 1 = [dbo].[DivisionCheck] (ssdept.divno,#tcDivNo)
In the three code samples shown, I see nothing that would generate that subquery error message.
exists() subqueries are designed to handle multilple returned rows
The select max() subquery is properly formed
There is nothing that would cause problems if the only subquery in the third block returned multiple rows
Ergo, it must be something else. My guess—and this is a guess—is that, in the third bock, tables v_est_joblist and/or v_depuse_qty are in fact views (I use something like the v_Blah convention myself), and something’s going wrong in one of them. If so, you’d need to test these views, see what they’re returning when joined into the main query as they are.
It appears that your "in" expression is being supplied with more than one row of values. So, although "exists" can accept multiple rows as input, "0 in (aastk.cartonratio1, ...) cannot.

Using MAX function for greatest value between a range

Pretty new to tsql functions, and I'm trying to write one that returns a value for the STC_STATUS for the greatest STC_STATUS_DATE where the STC_STATUS_DATE is <= the STC_START_DATE+9. They way I have it now, it returns a null value if there is a STC_STATUS > stc_start_date+9.
SELECT #Result1 = STC_STATUS
FROM STC_STATUSES ss
LEFT OUTER JOIN STUDENT_ACAD_CRED stc ON ss.STUDENT_ACAD_CRED_ID = stc.STUDENT_ACAD_CRED_ID
WHERE ss.STUDENT_ACAD_CRED_ID = ISNULL(#student_acad_cred_id, '0')
AND MAX(ss.STC_STATUS_DATE) <= DATEADD(day,9,stc.STC_START_DATE)
Any help would be greatly appreciated.
EDIT: Sample data per recommendation:
The function returns a null value because pos 1 has a stc_status date that is greater than stc_start_date+9. What I aim to have the function do is return the most recent status date below stc_start_date+9, which would be record 2 in this sample.
you can use TOP 1 to get the correct result
SELECT TOP 1 #Result1 = STC_STATUS
FROM STC_STATUSES ss
LEFT OUTER JOIN STUDENT_ACAD_CRED stc
ON ss.STUDENT_ACAD_CRED_ID = stc.STUDENT_ACAD_CRED_ID
WHERE ss.STUDENT_ACAD_CRED_ID = ISNULL(#student_acad_cred_id, '0')
AND ss.STC_STATUS_DATE <= DATEADD(day,9,stc.STC_START_DATE)
ORDER BY ss.STC_STATUS_DATE desc

SQL Server Case statement in WHERE Clause

I tried to google for CaseStatement in WHERE clause. But i didn't find similar to my scenario.
Below is my SQL Statement with CASE Statement in WHERE clause. If PartName = B, then i should apply (RecoveraleFlag = 1) condition along with other conditions. Else This condition should not apply but all other conditions should remain.
FROM Rec.Communications A
INNER JOIN REC.CommunicationTypes B ON A.CommunicationTypeKey = B.CommunicationTypeKey
INNER JOIN occ.Cases c ON a.CaseId = c.CaseId
INNER JOIN occ.Claims cl on a.CaseId = cl.CaseId
INNER JOIN ops.Concepts d ON c.ConceptKey = d.ConceptKey
INNER JOIN OPS.Regions f ON d.MODSRegionKey = f.MODSRegionKey
INNER JOIN COM.RepriceRequestOccurrences e ON a.CommunicationId = e.CommunicationId
INNER JOIN occ.Providers prv ON c.MODSProviderKey = prv.MODSProviderKey
WHERE
**(
CASE WHEN f.PartName = 'B' and e.RecoverableFlag = 1 then 1
ELSE 0
END
) = 1**
AND
b.CommunicationTypeCode = 'RREQ'
AND f.Region = #Region
AND a.CurrentFlag = 1
Here Case Statement in where clause is working fine if Partname = B. For Partname A, this will be 0=1 – always false. Because of this it is not returning any data.
Can anyone gives any alternatives.
As a case statement, you would write this as:
CASE WHEN f.PartName = 'B' and e.RecoverableFlag = 1 then 1
WHEN f.ParName = 'A' then 1
ELSE 0 END ) = 1
Is this the logic you want?
Many would think that the case statement is irrelevant here, and instead use:
WHERE ((f.PartName = 'B' and e.RecoverableFlag = 1) or (f.partName <> 'B')) . . .
WHERE
(
f.PartName <> 'B'
OR e.RecoverableFlag = 1
)
AND b.CommunicationTypeCode = 'RREQ'
AND f.Region = #Region
AND a.CurrentFlag = 1
You might find reading on De Morgan's Laws interesting.
I don't believe you need a case statement at all.. The following should work...
WHERE f.PartName = 'B'
And e.RecoverableFlag = 1
AND b.CommunicationTypeCode = 'RREQ'
AND f.Region = #Region
AND a.CurrentFlag = 1
But if you want to use a case statement in a where clause, try to put it on the "other" side of the comparison operator from the column name so the query can process it without doing a table scan...
as an e.g.,
Where f.Partname =
Case b.CommunicationTypeCode
When 'RREQ' Then 'B'
When 'NOTREQ' Then 'C'
When 'OPT' Then 'D'
Else 'F' End

Resources