Nested CASE WHEN statement - sql

I have one CASE WHEN condition (CompanyGUID and LineGUID) and I need 4 different calculations with 4 different columns.
The calculation works fine, but I just wonder is any way to make it more convenient? like for example maybe using COALESCE trick in this case?
CASE WHEN dbo.tblCompanyLocations.CompanyGUID = '29634AF7-D0A2-473D-9574-405C23E10F02'
AND dbo.tblQuotes.LineGUID = '1CB72920-B3FC-4822-8030-37B50A2810EB'
THEN isnull(ddaWC.archexMod,1)
END as ExperienceMod,
CASE WHEN dbo.tblCompanyLocations.CompanyGUID = '29634AF7-D0A2-473D-9574-405C23E10F02'
AND dbo.tblQuotes.LineGUID = '1CB72920-B3FC-4822-8030-37B50A2810EB'
THEN case when convert(int,ddawc.premModTtl) <= 0 then 1
when convert(int,ddawc.premModTtl) >= 0
then (1 + ddaWC.premschmod / ddawc.premModTtl) end
END as ScheduleMod,
CASE WHEN dbo.tblCompanyLocations.CompanyGUID = '29634AF7-D0A2-473D-9574-405C23E10F02'
AND dbo.tblQuotes.LineGUID = '1CB72920-B3FC-4822-8030-37B50A2810EB'
THEN isnull(ddaWC.TMpercent,1) END as TerritoryMod,
CASE WHEN dbo.tblCompanyLocations.CompanyGUID = '29634AF7-D0A2-473D-9574-405C23E10F02'
AND dbo.tblQuotes.LineGUID = '1CB72920-B3FC-4822-8030-37B50A2810EB'
THEN case when convert(int,ddaWC.SchedPercent) = 0 or
ddaWC.SchedPercent is not null
then (isnull(ddaWC.archexMod,1)
* (convert(decimal(5,2),isnull(ddaWC.SchedPercent,1))))
* isnull(ddaWC.TMpercent,1)
when ddaWC.SchedPercent is null
then 1 END
END as EffectiveMod

Something like this? The OUTER APPLY will perform a row-based select which return NULLs in case of your condition not being fullfilled. Otherwise it will return the same values you've specified. This will only work, if you really need the same logic for all columns.
SELECT otherColumn
,ConditionalColumns.*
FROM YourTable
OUTER APPLY
(
SELECT isnull(ddaWC.archexMod,1) as ExperienceMod,
case when convert(int,ddawc.premModTtl) <= 0 then 1
when convert(int,ddawc.premModTtl) >= 0
then (1 + ddaWC.premschmod / ddawc.premModTtl) end as ScheduleMod,
isnull(ddaWC.TMpercent,1) as TerritoryMod,
case when convert(int,ddaWC.SchedPercent) = 0 or ddaWC.SchedPercent is not null
then (isnull(ddaWC.archexMod,1)
* (convert(decimal(5,2),isnull(ddaWC.SchedPercent,1))))
* isnull(ddaWC.TMpercent,1)
when ddaWC.SchedPercent is null
then 1 END as EffectiveMod
WHERE dbo.tblCompanyLocations.CompanyGUID = '29634AF7-D0A2-473D-9574-405C23E10F02'
AND dbo.tblQuotes.LineGUID = '1CB72920-B3FC-4822-8030-37B50A2810EB'
) AS ConditionalColumns

Like this:
somewhere before code:
Declare #compGuid char(37) = '29634AF7-D0A2-473D-9574-405C23E10F02'
Declare #lineGuid char(37) = '1CB72920-B3FC-4822-8030-37B50A2810EB'
and modify From Clause in SQL statement to define aliases
cl for tblCompanyLocations, and
q for tblQuotes
then the case in the Select clause of the SQL code could be reduced to:
case when cl.CompanyGUID = #compGuid
and q.LineGUID = #lineGuid
then isnull(ddaWC.archexMod,1) end ExperienceMod,
case when cl.CompanyGUID = #compGuid
and q.LineGUID = #lineGuid
then case when cast(ddawc.premModTtl as int) > 0
then (1 + ddaWC.premschmod / ddawc.premModTtl)
else 1 end end ScheduleMod,
case when cl.CompanyGUID = #compGuid
and q.LineGUID = #lineGuid
then isnull(ddaWC.TMpercent,1) end TerritoryMod,
case when cl.CompanyGUID = #compGuid
and q.LineGUID = #lineGuid
then case when cast(ddaWC.SchedPercent as int) = 0
then isnull(ddaWC.archexMod,1)
* cast(ddaWC.SchedPercent as decimal(5,2)))
* isnull(ddaWC.TMpercent,1)
when ddaWC.SchedPercent is null
then 1 end end EffectiveMod
which is a bit more readable... (check the logic though)

Related

SQL Server - CASE on where clause

I'm working on a stored procedure that is a select query. Under the WHERE clause I am filtering the return results to return only if there is a PageTitle= 'STA'
Here is am example of my query :
#InputCountryId INT,
#InputIndustryId INT
AS
BEGIN
SELECT
r.IdCountry,
r.IdIndustry,
r.PageTitle,
r.IndustryName
From dbo.Reports r
WHERE
r.IdCountry = #InputCountryId
r.IdIndustry = #InputIndustryId
r.PageTitle = 'STA'
END
The ending condition r.PageTitle I would like it to be applied ONLY IF InputCountry = 1 if not; do not include the filter.
I've attempted this by including a CASE. I am having a syntax error any time I try and introduce this case. Is this something that is possible? Am I implementing it incorrectly?
Here is an example of the stored proc with the CASE included.
#InputCountryId INT,
#InputIndustryId INT
AS
BEGIN
SELECT
r.IdCountry,
r.IdIndustry,
r.PageTitle,
r.IndustryName
From dbo.Reports r
WHERE
r.IdCountry = #InputCountryId
r.IdIndustry = #InputIndustryId
CASE WHEN #InputCountryId = 1 THEN
r.PageTitle = 'STA'
END
END
Try it this way:
WHERE
r.IdCountry = #InputCountryId and
r.IdIndustry = #InputIndustryId and
(#InputCountryId <> 1 or r.PageTitle = 'STA')
You dont need case statement. You can use OR clause
WHERE
r.IdCountry = #InputCountryId
r.IdIndustry = #InputIndustryId
(#InputCountryId != 1 OR r.PageTitle = 'STA')
this only filters PageTitle with STA when InputCountry is 1
I can't test with your data, but here is a CASE in a WHERE clause that works.
DECLARE #Variable INT = 3
SELECT GETDATE()
WHERE 1 =
CASE
WHEN #Variable = 1 THEN 1
WHEN #Variable = 3 THEN 1
WHEN #Variable = 5 THEN 1
ELSE 0
END

Avoid calling a scalar function multiple times in a MERGE and UPDATE statement

I want to call function that return scalar multiple times.
How can I do that in a MERGE statement?
My code:
MERGE [dbo].MyTable m
USING (select * from Table2 edbl
where IsRowError = 0) edbTable
on edbTable.Filed1 = m.Filed1
WHEN MATCHED THEN UPDATE SET
m.Filed2 = case when dbo.func1(edbTable.Filed7) = 1 then 1
when dbo.func1(edbTable.Filed7) = 0 then 1
else 0 end,
m.Filed3 = case when dbo.func1(edbTable.Filed7) = 0 then 0 end,
m.Filed4 = case when dbo.func1(edbTable.Filed7) = 0 then 3 end,
m.Filed5 = case when dbo.func1(edbTable.Filed7) = 0 then 9 else 5 end,
m.Filed6 = getdate();
I want also to do it in UPDATE statement:
UPDATE md
set Filed1 = case when dbo.func1(edbl.Filed7) = 0 then 0 end,
Filed5 = case when dbo.func1(edbTable.Filed7)=0 then 9 else 5 end,
Filed6 = getdate()
from Table2 edbl
join Table3 m on edbl.Filed2= m.Filed2
join Table4 md on m.Filed3=md.Filed3
join Table5 mb on md.Filed4 = mb.Filed4
where IsRowError = 0
You can do it in the subquery:
MERGE [dbo].MyTable m
USING (select edbl.*, dbo.func1(edbTable.Filed7) as func1
from Table2 edbl
where IsRowError = 0
) edbTable
on edbTable.Filed1 = m.Filed1
WHEN MATCHED THEN UPDATE SET
m.Filed2 = (case when func1 = 1 then 1
when func1 = 0 then 1
else 0
end),
m.Filed3 = case when func1 = 0 then 0 end,
m.Filed4 = case when func1 = 0 then 3 end,
m.Filed5 = case when func1 = 0 then 9 else 5 end,
m.Filed6 = getdate();
However, it is not clear that this is a big win. If most rows do not match, this might not be a big improvement.
You could do it once inside USING part:
MERGE [dbo].MyTable m
USING (select *, dbo.func1(Filed7) AS f from Table2 edbl
where IsRowError = 0) edbTable
on edbTable.Filed1 = m.Filed1
WHEN MATCHED THEN UPDATE SET
m.Filed2 = case when f = 1 then 1
when f = 0 then 1
else 0 end,
m.Filed3 = case when f = 0 then 0 end,
m.Filed4 = case when f = 0 then 3 end,
m.Filed5 = case when f = 0 then 9 else 5 end,
m.Filed6 = getdate();
You can use APPLY with UPDATE statement :
UPDATE md
SET Filed1 = CASE WHEN fun = 0 THEN 0 END,
Filed5 = CASE WHEN fun = 0 THEN 9 ELSE 5 END,
Filed6 = getdate()
FROM Table2 edbl JOIN
Table3 m
ON edbl.Filed2 = m.Filed2 JOIN
Table4 md
ON m.Filed3 = md.Filed3 JOIN
Table5 mb
ON md.Filed4 = mb.Filed4 CROSS APPLY
( VALUES (dbo.func1(edbl.Filed7))
) edbl1(fun)
where IsRowError = 0;

If else ladder using Case in sql server

I am trying to write if elif ladder in SQL but I am finding it little difficult to do that. My ladder looks like below.
IF (MortgageProduct.FreeLegalFees != NULL) THEN
IF(MortgageProduct.FreeLegalFees==1) THEN
Return TRUE as FreeLegalFees
ELSE
Return FALSE as FreeLegalFees
ELSE
IF (ConveyancerFee!=NULL) THEN
IF ConveyancerFee.AMOUNT = 0.0 then
Return TRUE as FreeLegalFees
ELSE
Return FALSE as FreeLegalFees
END IF
ELSE
IF (LenderFee!=NULL) THEN
IF LenderFee.AMOUNT = 0.0 then
Return TRUE as FreeLegalFees
ELSE
Return FALSE as FreeLegalFees
END IF
ELSE
Return TRUE as FreeLegalFees
END IF
I know that I have to use Case for that in SQL but I am confuse in writing Case statement in sql. Can somebody please help me to frame this ladder in sql server.
This is far more succinct. I have also aliased what I assume are your table names:
CASE WHEN MP.FreeLegalFees IS NOT NULL THEN IIF(MP.FreeLegalFees = 1,1,0)
WHEN CF.AMOUNT IS NOT NULL THEN IIF(CF.AMOUNT = 0,1,0)
WHEN LF.Amount IS NOT NULL THEN IIF(LF.AMOUNT = 0,1,0)
ELSE 1 END
/*
MP MortgageProduct
CF ConveyancerFee
LF LenderFee
*/
I would write this as:
(case when mp.FreeLegalFees = 1 then 1
when mp.FreeLegalFees is not null then 0
when cf.amount = 0.0 then 1
when cf.amount is not null then 0
when lf.amount = 0.0 then 1
when lf.amount is not null then 0
else 1
end) as FreeLegalFees
CASE
WHEN MP.FREELEGALFEES = 1 THEN 1
WHEN MP.CONVEYANCERLEGALFEESET IS NOT NULL THEN
(
CASE
WHEN (
(SELECT AMOUNT FROM CONVEYANCERLEGALFEE WHERE LOCATION=#p_iLocation
and TYPEOFAPPLICATION=#p_iTypeOfApplication
and TYPEOFBUYER=#p_iTypeOfBuyer and MAXIMUMVALUE=100000
and CONVEYANCERLEGALFEESETSTRTDATE <= (SELECT GETDATE())
and CONVEYANCERLEGALFEESET = MP.CONVEYANCERLEGALFEESET ) = 0.0)
THEN 1
ELSE 0
END
)
WHEN ((Select COUNT(FEESET) FROM LEGALFEE WHERE TYPEOFAPPLICATION=#p_iTypeOfApplication
AND FEETYPE = (Select VALUEID from COMBOVALUE where VALUENAME='Redeeming')) >= 1 ) THEN
(
CASE
WHEN (
(SELECT AMOUNT FROM LEGALFEE
WHERE TYPEOFAPPLICATION = #p_iTypeOfApplication
AND FEETYPE= (SELECT VALUEID FROM COMBOVALUE WHERE VALUENAME='Redeeming')) = 0.0)
THEN 1
ELSE 0
END
)
ELSE 1
This is the solution which works perfect. Thank you all.
CASE
WHEN MortgageProduct.FreeLegalFees IS NOT NULL
THEN (
CASE
WHEN MortgageProduct.FreeLegalFees = 1
THEN 'TRUE'
ELSE 'FALSE'
END
)
WHEN ConveyancerFee IS NOT NULL
THEN (
CASE
WHEN ConveyancerFee.AMOUNT = 0.0
THEN 'TRUE'
ELSE 'FALSE'
END
)
WHEN LenderFee IS NOT NULL
THEN (
CASE
WHEN LenderFee.AMOUNT = 0.0
THEN 'TRUE'
ELSE 'FALSE'
END
)
ELSE 'TRUE'
END AS FreeLegalFees

SQL Server conditional where clause

I have the following where clause that begins with the following:
DECLARE #Birthdate = 1
SELECT ...
FROM ...
JOIN ...
WHERE A.organization_id = 1
AND LEFT(A.[first_name], 3) = LEFT(B.[first_name], 3)
AND LEFT(A.[last_name], 3) = LEFT(B.[last_name], 3)
After this I would like to conditionally execute additional clauses.
For example:
if #Birthdate = 1 then add AND A.[birthdate] = B.[birthdate]
otherwise, don't add anything
I've tried the following and none seem to work properly:
Ex 1:
AND (#Birthdate = 1 AND A.[birthdate] = B.[birthdate])
Ex 2:
AND ((#Birthdate = 1 AND A.[birthdate] = B.[birthdate]) OR
(#Birthdate = 0 AND (A.[birthdate] = B.[birthdate] OR
A.[birthdate] <> B.[birthdate])))
Any suggestions as to what I'm doing wrong?
You can use an or to apply your filter, or to just return all rows when #Birthdate = 0
SELECT
...
FROM
...
WHERE
(
-- Apply the filter if applicable
(
#Birthdate = 1
and A.[birthdate] = B.[birthdate]
)
-- Or return everything
or #Birthdate <> 1
)

Concatenating multiple CASE statements into one alias

After some previous help on how to approach a problem I am having with some legacy code, it seems like the best approach for my issue is to concatenate case statements to return a value I can parse out in PHP.
I am trying to do something like this, but it is returning many rows, and eventually getting this error:
Maximum stored procedure, function, trigger, or view nesting level
exceeded (limit 32).
SELECT org.org_id,
org.org_name_1,
Datename(YEAR, member.enroll_date) AS enroll_year,
Max(CASE
WHEN board.member_from IS NULL THEN 0
ELSE 1
END) AS board_member,
CASE
WHEN ( org.delete_reason = 'OUT'
AND org.org_delete_flag = 'Y'
AND org.org_status_flag = 'C' ) THEN 'out_of_business|'
ELSE ''
END + CASE
WHEN ( stat.carrier = 'BS'
AND stat.status_id IS NOT NULL
AND stat.termination_date IS NULL
AND stat.flat_dues > 0 ) THEN 'insurance_member|'
ELSE ''
END + CASE
WHEN ( stat.carrier = 'BS'
AND stat.status_id IS NOT NULL
AND stat.termination_date IS NULL
AND stat.flat_dues = 0
AND member.status_flag IN( 'C', 'P' ) ) THEN 'insurance_product|'
ELSE ''
END + CASE
WHEN ( member.enroll_date IS NOT NULL
AND member.status_flag NOT IN( 'C', 'P' ) ) THEN 'member_since|'
ELSE ''
END + CASE
WHEN ( org.org_relationship_parent = 'Y'
AND org.dues_category = 'MBR'
AND org.org_status_flag = 'R' ) THEN 'subsidiary_member|'
ELSE ''
END + CASE
WHEN ( org.org_misc_data_9 = 'PAC' ) THEN 'pac|'
ELSE ''
END + CASE
WHEN ( org.dues_category = 'PART' ) THEN 'partner_member|'
ELSE ''
END + CASE
WHEN ( org.dues_category = 'FREE'
AND org.org_status_flag = 'P' ) THEN 'associate_member|'
ELSE ''
END
--ELSE 'non_member'
--END
AS org_status,
60 AS expires_in,
CASE
WHEN stat.dues_type = 'M' THEN
CASE
WHEN ( stat.termination_date IS NULL ) THEN ( stat.flat_dues )
ELSE 0
END
ELSE
CASE
WHEN ( member.payments = 0 ) THEN member.dues_billed_annual
ELSE member.payments
END
END AS dues_level,
CASE
WHEN ( org.affiliate_code = 'PCCE'
AND org.dues_category = 'MBR'
AND org.org_status_flag = 'R' ) THEN 1
ELSE 0
END AS pcce_membr,
-- '$'+CONVERT(VARCHAR,#dues) AS dues_level,
Ltrim(#product_level) AS product_level,
Ltrim(#involve_level) AS involvement_level
FROM organiz AS org
LEFT JOIN affilbil AS member
ON member.status_id = org.org_id
AND member.dues_category = 'MBR'
LEFT JOIN individu AS ind
ON ind.org_id = org.org_id
LEFT JOIN commembr AS board
ON board.status_id = ind.ind_id
AND board.committee_code = '5'
AND board.member_to IS NULL
LEFT JOIN statinsmorn AS stat
ON stat.status_id = org.org_id
AND stat.carrier = 'BS'
AND stat.planz = 'PCI'
WHERE org.org_id = #org_id
GROUP BY org.org_id,
org.org_name_1,
member.enroll_date,
org.delete_reason,
org.org_status_flag,
org.org_delete_flag,
stat.status_id,
stat.flat_dues,
stat.dues_type,
stat.termination_date,
org.org_misc_data_9,
org_relationship_parent,
org.dues_category,
member.status_flag,
member.dues_billed_annual,
member.payments,
stat.carrier,
org.Affiliate_Code
Well, this is embarrassing.
When I was making my changes to the stored procedure, I had inadvertently placed a call to the same procedure at the bottom. So I was recursively calling the same procedure over and over again. DOH.