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.
Related
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.
I inherited a spreadsheet from a co-worker who used a nested If statement as shown below:
=IF(AND([#[Pred Type]]="PR_FS",[#[ST Finish]]="A"),
0,
IF(AND([#[Pred Type]]="PR_SS", OR([#[ACT_START_DATE]]<>0,[#[ST Start]]="A")),
0,
IF(AND([#[Pred Type]]="PR_SF",OR([#[ACT_START_DATE]]<>0,[#[ST Start]]="A")),
0,
IF(AND([#[Pred Type]]="PR_FF",[#[STFinish]]="A"),0,1)
)
)
)
I know I can write a CASE statement that would mimic this but can't figure out the syntax for it. I tried:
,CASE WHEN #Preds.Pred_Type = 'PR_FS' and #Tbl_Sched_Act.Expected_Finish = 'A' THEN 0
WHEN #Preds.Pred_Type = 'PR_SS' OR ACT_START_DATE IS NOT NULL OR Start_RAW IS NOT NULL THEN 0
WHEN #Preds.Pred_Type = 'PR_SF'OR ACT_START_DATE IS NOT NULL OR Start_RAW IS NOT NULL THEN 0
WHEN #Preds.Pred_Type = 'PR_FF' and #Tbl_Sched_Act.Expected_Finish = 'A' THEN 0
ELSE 1
END as PRED_MET
However, the CASE statement does not evaluate any of the items to be equal to 1. They all evaluate to 0 which isn't correct.
Does anyone have any idea on how I could write my CASE statement correctly?
You need to group the OR inside parenthesis () to force operator precedence.
CASE
WHEN #Preds.Pred_Type = 'PR_FS' and #Tbl_Sched_Act.Expected_Finish = 'A'
THEN 0
WHEN #Preds.Pred_Type = 'PR_SS'
AND (ACT_START_DATE <> 0 OR Start_RAW <> 0)
THEN 0
WHEN #Preds.Pred_Type = 'PR_SF'
AND (ACT_START_DATE <> 0 OR Start_RAW <> 0)
THEN 0
WHEN #Preds.Pred_Type = 'PR_FF' and #Tbl_Sched_Act.Expected_Finish = 'A'
THEN 0
ELSE 1
END as PRED_MET
NOTE:: If a number is <> 0 then also is NOT NULL DEMO
But that can also be simplify to:
CASE
WHEN #Tbl_Sched_Act.Expected_Finish = 'A'
AND #Preds.Pred_Type IN ('PR_FS', 'PR_FF')
THEN 0
WHEN (ACT_START_DATE <> 0 OR Start_RAW <> 0)
AND (#Preds.Pred_Type IN ('PR_SS','PR_SF')
THEN 0
ELSE 1
END as PRED_MET
Can anyone explain me why these two statements returns different results?
SELECT CASE WHEN NOT((NULL = NULL) OR (1 != 1)) THEN 1 ELSE 0 END
SELECT CASE WHEN NOT((NULL = NULL) AND (1 != 1)) THEN 1 ELSE 0 END
I know that NULL compared with anything gives false and I wanted to use that property but I stopped at commands similar to above. My real statements instead of NULLs use variables that can be NULL but I simplified them to show where is the problem. I thought that it has something with operation order but it seems that's not it.
I know that NULL compared with anything gives false
This isn't correct, NULL compared with anything evaluates to unknown, not false, a quick example:
SELECT CASE WHEN (NULL = NULL) THEN 'True'
WHEN NOT(NULL = NULL) THEN 'False'
ELSE 'Other'
END
Will give the third option of Other.
If we rewrite your logic (still the same meaning, but it becomes more clear):
SELECT CASE WHEN (NULL <> NULL) AND (1 = 1) THEN 1 ELSE 0 END
SELECT CASE WHEN (NULL <> NULL) OR (1 = 1) THEN 1 ELSE 0 END
So in the first instance you have WHEN [Unknown] AND [True] which is false, but in the second you have WHEN [Unknown] OR [True] which is true, so returns 1.
If you rewrite the query with variables, then inspect the execution plan XML, you can see that SQL Server rewrites the expression as above during compilation:
DECLARE #a INT = NULL, #b INT = NULL, #c INT = 1, #d INT = 1;
SELECT TOP 1
CASE WHEN NOT((#a = #b) OR (#c != #d)) THEN 1 ELSE 0 END,
CASE WHEN NOT((#a = #b) AND (#c != #d)) THEN 1 ELSE 0 END
-- first query
SELECT CASE WHEN NOT((NULL = NULL) AND (1 != 1)) THEN 1 ELSE 0 END
=
SELECT CASE WHEN NOT(unknown AND false) THEN 1 ELSE 0 END
=
SELECT CASE WHEN NOT(false) THEN 1 ELSE 0 END
=
SELECT CASE WHEN true THEN 1 ELSE 0 END
=
1
-- second query
SELECT CASE WHEN NOT((NULL = NULL) OR (1 != 1)) THEN 1 ELSE 0 END
=
SELECT CASE WHEN NOT(unknown OR false) THEN 1 ELSE 0 END
=
SELECT CASE WHEN NOT(unknown) THEN 1 ELSE 0 END
=
SELECT CASE WHEN unknown THEN 1 ELSE 0 END
=
else matched, so 0
And to D0dger's question from comments:
It's more interesting why SELECT CASE WHEN (NULL = NULL) OR (1 != 1) THEN 1 ELSE 0 END and SELECT CASE WHEN NOT((NULL = NULL) OR (1 != 1)) THEN 1 ELSE 0 END returns 0
SELECT CASE WHEN (NULL = NULL) OR (1 != 1) THEN 1 ELSE 0 END
=
SELECT CASE WHEN unknown OR false THEN 1 ELSE 0 END
=
SELECT CASE WHEN unknown THEN 1 ELSE 0 END
=
else matched, so 0
OR (Transact-SQL), AND (Transact-SQL)
So, there are 2 options: Either you have ANSI_NULLS ON (and you should) or you have ANSI_NULLS OFF.
In the first case, any comparison with NULL returns NULL (even comparisons between NULL values such as yours).
In the second case, sql server will evaluate comparisons between NULL values (e.g. NULL=NULL will return true).
So before considering the different results in your queries you must first consider that comparing NULL with anything, doesn't evaluate to false but NULL
When i run the following query, an error occurred saying:
A SELECT statement that assigns a value to a variable must not be
combined with data-retrieval operations.
How should I fix this?
Here is the query:
DECLARE #loanInstallmet float
SELECT TOP (1)
loan.loanID,members.offno AS OfficialNumber,
loan.loanAmount,
loan.interestRate,
loan.NoOfInstallment,
loanHistory.presentInstallmentNo,
loanHistory.dateBalanceUpdate,
(loanHistory.presentInstallmentNo + 1) AS InstallmentNo,
members.monthllyContribution AS MonthlyContribution,
#loanInstallmet =
CASE
WHEN loan.remarks = 'Half' THEN ROUND(loanHistory.balanceAmount/ (loan.NoOfInstallment-loanHistory.presentInstallmentNo ), 0)
ELSE ROUND((loan.loanAmount / loan.NoOfInstallment), 0)
END,
CASE
WHEN loanHistory.presentInstallmentNo % 12 = 0 THEN ROUND(((loan.loanAmount-loanHistory.balanceAmount) * loan.interestRate / 1200), 0)
ELSE ROUND((loan.loanAmount * loan.interestRate / 1200), 0)
END AS MonthlyInterest,
LEFT(DATENAME(MONTH,Getdate()),3)as recMonth,
year(GETDATE())as recYear,
loan.isRecovered as LoanIsRecovered,
members.memberIsActive,
loanHistory.status,
ROUND((loanHistory.balanceAmount-#loanInstallmet), 0) AS BalanceAmount,
loan.remarks
FROM loan
INNER JOIN members
ON loan.offNo = members.offno
INNER JOIN loanHistory
ON members.offno = loanHistory.offNo
AND loan.loanID = loanHistory.loanID
WHERE
loan.isRecovered = 0
AND members.memberIsActive = 1
order by loanHistory.presentInstallmentNo DESC
It is saying what it means ! ;)
You can't do:
SELECT TOP (1) loan.loanID,members.offno AS OfficialNumber, ....
at the same time as:
SELECT #loanInstallmet = CASE WHEN loan.remarks = 'Half' THEN
You are either retrieving data for your application, or you are setting the value of a variable. It's not logical to do both at the same time.
If you want to calculate #loanInstallmet and use it in future calculations you can do something like the following:
With tblLoanInstallCalc as (
SELECT TOP (1) loan.loanID,members.offno AS OfficialNumber,loan.loanAmount,loan.interestRate,loan.NoOfInstallment,loanHistory.presentInstallmentNo,loanHistory.dateBalanceUpdate,(loanHistory.presentInstallmentNo + 1) AS InstallmentNo, members.monthllyContribution AS MonthlyContribution,
CASE WHEN loan.remarks = 'Half' THEN ROUND(loanHistory.balanceAmount/ (loan.NoOfInstallment-loanHistory.presentInstallmentNo ), 0) ELSE ROUND((loan.loanAmount / loan.NoOfInstallment), 0) END AS loanInstallmet,
CASE WHEN loanHistory.presentInstallmentNo%12 = 0 THEN ROUND(((loan.loanAmount-loanHistory.balanceAmount) * loan.interestRate / 1200), 0) ELSE ROUND((loan.loanAmount * loan.interestRate / 1200), 0) END AS MonthlyInterest,
LEFT(DATENAME(MONTH,Getdate()),3)as recMonth,year(GETDATE())as recYear ,loan.isRecovered as LoanIsRecovered, members.memberIsActive, loanHistory.status, loan.remarks
FROM loan INNER JOIN
members ON loan.offNo = members.offno INNER JOIN
loanHistory ON members.offno = loanHistory.offNo AND loan.loanID = loanHistory.loanID
WHERE (loan.isRecovered = 0) AND (members.memberIsActive = 1)
)
Select *, ROUND((balanceAmount-loanInstallmet), 0) AS BalanceAmount
From tblLoanInstallCalc
tblLoanInstallCalc is a common table expression (CTE) and is pre-calculating the prerequisites before you try to add up the balance
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