SQL - WHERE with CASE statement - sql

SELECT TOP 1
CostValue
FROM
[~client_table~].[dbo].[CostRules] AS CostRule
WHERE
(CASE
WHEN DATALENGTH(CostRule.ModelName) = 0
THEN
CostRule.Type = 1
AND CostRule.Manufacturer = Printer.ManufacturerId
AND CostRule.ColorType = 1
ELSE
CostRule.Type = 2
AND CostRule.ModelName = Printer.ModelName
AND CostRule.ColorType = 1
END
)
) AS MonoCost
I want to define my where statement depending on the datalength of CostRule.ModelName. But i got an error: Incorrect syntax near '='. in CostRule.Type = 1 and i got a error in the ELSE statement.

Must be like this:
...
WHERE
(DATALENGTH(CostRule.ModelName) = 0
AND CostRule.Type = 1
AND CostRule.Manufacturer = Printer.ManufacturerId
AND CostRule.ColorType = 1)
OR
(DATALENGTH(CostRule.ModelName) != 0
AND CostRule.Type = 2
AND CostRule.ModelName = Printer.ModelName
AND CostRule.ColorType = 1)
The CASE-style from your query cannot work.

you can change your statement like this:
SELECT TOP 1
CostValue
FROM
[~client_table~].[dbo].[CostRules] AS CostRule
WHERE CostRule.ColorType=1
AND CostRule.Type=CASE WHEN DATALENGTH(CostRule.ModelName) = 0 THEN 1 ELSE 2 END
AND CostRule.Manufacturer=CASE WHEN DATALENGTH(CostRule.ModelName) = 0 THEN Printer.ManufacturerId ELSE Printer.ModelName END

You can't use a CASE statement to define where conditions like that. It will be easier to just use some boolean logic
SELECT *
FROM your_table
WHERE (DATALENGTH(CostRule.ModelName) = 0
AND CostRule.Type = 1
AND CostRule.Manufacturer = Printer.ManufacturerId
AND CostRule.ColorType = 1)
OR (DATALENGTH(CostRule.ModelName) != 0
AND CostRule.Type = 2
AND CostRule.ModelName = Printer.ModelName
AND CostRule.ColorType = 1)
There are some other things that could be removed (like CostRule.ColorType = 1 since it is the same in both branches) but I've left them in here to illustrate how to transform your CASE statement into a boolean logic set.

It looks like you would just need to change the WHERE statement:
It looks like you will just need to change your WHERE statement to use OR and remove the CASE Statement.
(SELECT TOP 1
CostValue
FROM
[~client_table~].[dbo].[CostRules] AS CostRule
WHERE
DATALENGTH(CostRule.ModelName) = 0
CostRule.Type = 1
AND CostRule.Manufacturer = Printer.ManufacturerId
AND CostRule.ColorType = 1
OR
DATALENGTH(CostRule.ModelName) <> 0
AND CostRule.Type = 2
AND CostRule.ModelName = Printer.ModelName
AND CostRule.ColorType = 1
) AS MonoCost

Related

Filter only get one condition

I have a validation in WHERE clause like:
...
AND (#BDOnly = 0
OR [DT].[Abbreviation] = #IsBDChecked)
AND (#CDOnly = 0
OR [DT].[Abbreviation] = #IsCDChecked)
AND (#PPOOnly = 0
OR [DT].[Abbreviation] = #IsPPOChecked)
AND (#FBOMOnly = 0
OR [DT].[Abbreviation] = #IsFBOMChecked)
AND (#APOnly = 0
OR [DT].[Abbreviation] = #IsAPChecked)
AND (#COOnly = 0
OR [DT].[Abbreviation] = #IsCOChecked)
So each AND clause check if boolean is bit value is 0 or 1, if it's 0 just do any but if it's 1 it do a filter. My problem is
if I'm sending two with value 1, I mean
#BDOnly = 1 and #CDOnly = 1 it only filter one of them instead get two filters I mean:
[DT].[Abbreviation] = #IsBDChecked
and
[DT].[Abbreviation] = #IsCDChecked
What am I doing wrong? Regards
I'm going to take a guess here because there's not enough data. If you want to return a row where Abbreviation matched #IsBDChecked only when #BDOnly is set, and also another row where Abbreviation matches #IsCDChecked when #CDOnly is set, try this:
(#BDOnly = 1
AND [DT].[Abbreviation] = #IsBDChecked)
OR (#CDOnly = 1
AND [DT].[Abbreviation] = #IsCDChecked)
OR (#PPOOnly = 1
AND [DT].[Abbreviation] = #IsPPOChecked)
OR (#FBOMOnly = 1
AND [DT].[Abbreviation] = #IsFBOMChecked)
OR (#APOnly = 1
AND [DT].[Abbreviation] = #IsAPChecked)
OR (#COOnly = 1
AND [DT].[Abbreviation] = #IsCOChecked)
Small representative case:
DECLARE #ADOnly BIT = 0
, #BDOnly BIT = 1
, #CDOnly BIT = 1
, #IsADChecked NVARCHAR(100) = 'A'
, #IsCDChecked NVARCHAR(100) = 'C'
, #IsBDChecked NVARCHAR(100) = 'B'
;WITH myTable AS
(
SELECT * FROM (VALUES ('A'), ('B'), ('C')) X(Abbreviation)
)
SELECT *
FROM myTable
WHERE (#ADOnly = 1 AND Abbreviation = #IsADChecked)
OR (#BDOnly = 1 AND Abbreviation = #IsBDChecked)
OR (#CDOnly = 1 AND Abbreviation = #IsCDChecked)
Yields:
Abbreviation
------------
B
C

Case statement and OR in SQL

Can someone please advise on the below? I have a number of fields which I would like to use and combine these to get the data in one column. I am using the following case statement but am not getting the results I expect.
CASE
WHEN m.u_hearing = 1 THEN 'Hearing'
WHEN m.u_learning_reading_diff = 1 THEN 'Learning or reading Difficulty'
WHEN m.u_long_term_ill = 1 THEN 'Long Term Illness'
WHEN m.u_mental_illness = 1 THEN 'Mental Illness'
WHEN m.u_mobility = 1 THEN 'Mobility'
WHEN m.u_physical_coordination = 1 THEN 'Physical Co-ordination'
WHEN m.u_physical_dis = 1 THEN 'Physical Disability'
WHEN m.u_red_physical_cap = 1 THEN 'Reduced_physical_capacity'
WHEN m.u_speech = 1 THEN 'Speech'
WHEN m.u_vision = 1 THEN 'Vision'
WHEN m.u_other_dis = 1 THEN 'Other_Disability'
WHEN (m.u_hearing = 1 AND (m.u_learning_reading_diff = 1 OR (m.u_speech = 1))) THEN 'Multiple'
It is the last statement that is not giving the result I would like as if there are multiple fields with Yes then I would like multiple returned but it seems it is picking the first case.
Put the "hardest" condition first
case WHEN m.u_hearing = 1 AND (m.u_learning_reading_diff = 1 OR m.u_speech = 1) THEN 'Multiple'
WHEN m.u_hearing = 1 THEN 'Hearing' ...
Because a case stops at the first condition that is true
When using CASE statements, they will function in the order you have specified.
So if m.u_Hearing = 1 then it will stop at the first line and not reach the bottom one.
This will work for what you require, however list it in the order you prefer.
CASE
WHEN (m.u_hearing = 1 AND (m.u_learning_reading_diff = 1 OR (m.u_speech = 1))) THEN 'Multiple'
WHEN m.u_hearing = 1 THEN 'Hearing'
WHEN m.u_learning_reading_diff = 1 THEN 'Learning or reading Difficulty'
WHEN m.u_long_term_ill = 1 THEN 'Long Term Illness'
WHEN m.u_mental_illness = 1 THEN 'Mental Illness'
WHEN m.u_mobility = 1 THEN 'Mobility'
WHEN m.u_physical_coordination = 1 THEN 'Physical Co-ordination'
WHEN m.u_physical_dis = 1 THEN 'Physical Disability'
WHEN m.u_red_physical_cap = 1 THEN 'Reduced_physical_capacity'
WHEN m.u_speech = 1 THEN 'Speech'
WHEN m.u_vision = 1 THEN 'Vision'
WHEN m.u_other_dis = 1 THEN 'Other_Disability'
From what I know you cannot use your first statement again in another "when" like your
WHEN m.u_hearing = 1 THEN 'Hearing'
Above condition try to use else if it is working and feasible for you in end.
Else 'Multiple'

SQL CASE Clauses with variable

I get this error:
Incorrect syntax near '='.
Code:
WHERE
T.[ID] = -9769
AND TNS.Active = 1
AND CASE
WHEN T.[StatusID] IN (1,6)
THEN (T.[AuditUser_ID] = 2 AND TNX.Actor = 2)
END
WHERE
T.[ID] = -9769
AND TNS.Active = 1
AND 1 = CASE
WHEN T.[StatusID] IN (1,6)
and (T.[AuditUser_ID] = 2 AND TNX.Actor = 2) then 1 else 0
END

Understanding case expression in the "Where" clause

I've got this code here and you can see from my Pseudocode what I'm trying to accomplish
select *
from dbo.BenefitsForms
inner join Dependents on BenefitsForms.UserId = Dependents.BenefitsForm_UserId
inner join CoverageLevels on BenefitsForms.MedicalId = CoverageLevels.Id
where (BenefitsForms.MedicalId > 0 AND BenefitsForms.MedicalId < 13)
AND Dependents.IsSpouse = CASE when CoverageLevels.[Level] = 2 then 1
when CoverageLevels.[Level] = 3 then 0 end
when CoverageLevels.[Level] = 4 then [any, it doesnt matter] <--- my desire but it doesn't work.
What can I do to get the effect I desire in the brackets? If Coverage Level = 4 then I don't care what Dependents.IsSpouse is, I don't even need to sort by it anymore.
Assuming that isSpouse can only be 0 or 1... if CoverageLevels.Level is 4, then compare isSpouse to itself, which will always result in true:
AND Dependents.IsSpouse = CASE
when CoverageLevels.[Level] = 2 then 1
when CoverageLevels.[Level] = 3 then 0
when CoverageLevels.[Level] = 4 then Dependents.IsSpouse
END
Alternately, this can also be expressed without the CASE:
WHERE
BenefitsForms.MedicalId > 0
AND BenefitsForms.MedicalId < 13
AND (
(Dependents.IsSpouse = 1 AND CoverageLevels.[Level] = 2)
OR (Dependents.IsSpouse = 0 AND CoverageLevels.[Level] = 3)
OR CoverageLevels.[Level] = 4
)

Conditional operator in Transact-sql

Is there a way to do this shorter, for instance using some sort of conditional operator in Transact-sql?
IF #ParentBinaryAssetStructureId = -1
BEGIN
SET #ParentBinaryAssetStructureId = NULL
END
UPDATE BinaryAssets.BinaryAssetStructures
SET ParentBinaryAssetStructureId = #ParentBinaryAssetStructureId
WHERE BinaryAssetStructureId = #OriginalBinaryAssetStructureId
USE NULLIF()
UPDATE BinaryAssets.BinaryAssetStructures
SET ParentBinaryAssetStructureId = NULLIF(#ParentBinaryAssetStructureId,-1)
WHERE BinaryAssetStructureId = #OriginalBinaryAssetStructureId
The ternary (conditional) operator in c like languages:
x = doSomething ? 5 : 7
would be written like this in SQL:
SELECT #x = CASE WHEN #doSomething = 1 THEN 5 ELSE 0 END
There can be multiple cases (when clauses):
SELECT #x = CASE WHEN #doSomething = 1 THEN 5 WHEN #somethingElse = 1 THEN 20 ELSE 0 END
UPDATE BinaryAssets.BinaryAssetStructures
SET ParentBinaryAssetStructureId =
CASE ParentBinaryAssetStructureId
WHEN -1 THEN NULL
ELSE ParentBinaryAssetStructureId
END
WHERE BinaryAssetStructureId = #OriginalBinaryAssetStructureId
Give that a whirl