Case statement in where clause not working - sql

Friends..
I am using stored procedure in which there is an optional parameter #equal and default value is NULL. If user give some value to the parameter SQL query has to be changed. I am trying to use Case in Where clause. but its showing some error.
Help me with proper syntax or with better logic
My requirement is When user doesn't give value for #equal then
FiscalYear<#yr
Else
FiscalYear<=#yr
Select BankCode,(SUM(Debit)-SUM(Credit)) Amt
From vwDailyData
Where Pname=#ParishName and FiscalYear< (CASE WHEN #equal IS NULL THEN #yr ELSE '='+#yr)
and BankCode<>'Cash'
Group By BankCode
Modified Question
Select BankCode,(SUM(Debit)-SUM(Credit)) Amt
From vwDailyData
Where Pname=#ParishName AND (CASE WHEN #equal IS NULL THEN FiscalYear < #yr ELSE FiscalYear <= #yr END)
and BankCode<>'Cash'
Group By BankCode
Error statement
Msg 102, Level 15, State 1, Procedure spDisplayBankConsolidate, Line 14
Incorrect syntax near '<'.

You have two errors in your condition:
CASE expression lacks END, and
You cannot supply a different operator inside a CASE expression.
The condition should look like this:
WHERE Pname=#ParishName AND
((#equal IS NULL AND FiscalYear < #yr) OR (#equal IS NOT NULL AND FiscalYear <= #yr))
AND BankCode<>'Cash'
Note the #equal IS NULL and #equal IS NOT NULL conditions in two parts of the OR expression. Since the two are mutually exclusive, only one side of the OR will be deciding what rows to include in the query result.

Related

Select with IF statement on postgresql

I have a code like that:
select
tbl.person
,COUNT(distinct tbl.project)
,if (tbl.stage like '%SIGNED%') then sum(tbl.value) else '0' end if as test
from
my_table tbl
group by
1
And it returns me that error message:
SQL Error [42601]: ERROR: syntax error at or near "then"
I didn't got it. As I saw on documentation, the if statement syntax appears to be used correctly
IF is to be used in procedures, not in queries. Use a case expression instead:
select
tbl.person
,COUNT(distinct tbl.project)
,sum(case when tbl.stage like '%SIGNED%' then tbl.value else 0 end) as test
from
my_table tbl
group by
1
Notes:
tbl.stage is not part of the group by, so it should most probably be enclosed within the aggregate expression, not outside of it
all values returned by a case expression need to have the same datatype. Since sum(tbl.value) is numeric, the else part of the case should return 0 (number), not '0' (string).
In Postgres, I would recommend using filter:
select tbl.person, COUNT(distinct tbl.project)
sum(tbl.value) filter (where tbl.stage like '%SIGNED%') as test
from my_table tbl
group by 1;
if is control flow logic. When working with queries, you want to learn how to think more as sets. So the idea is to filter the rows and add up the values after filtering.
replace
if (tbl.stage like '%SIGNED%') then sum(tbl.value) else '0' end if as test
with
sum(case when tbl.stage like '%SIGNED%' then tbl.value end) as test

How to test a condition in a sql case statement on numbers

I would like to substitute all the values that are greater or equal to 10 with an empty string with a SQL CASE statement on my Microsoft SQL Server 2017. However, I am getting an error that reads:
Msg 102, Level 15, State 1, Line 13
Incorrect syntax near '>'.
Though there are some questions similar to my question, I can not find an answer that is specifically answering my question. For example this question here how to use > = condition in sql case statement?. I have also tried a dynamic query with a temporal table and this did not help.
Here is my code with the table definition and the test data as well as the actual query that I am running.
--table definition with two columns
declare #table table
(
person nvarchar(20),
digit decimal(10,2)
)
--insert test data with two records
insert into #table
select 'titimo', 9.51
union
select 'neriwo', 12.25
--the requirement is to not show the digit value if it is greater or equal to 10, but rather display an empty field.
--so, this is my select statement to meet this requirement that is failing
--with error message 'Incorrect syntax near >'
select
person,
case digit
when digit >= 10 then ''
else digit
end 'digit'
from #table
From my select statement above, I am expecting this output:
person digit
------ -----
titimo 9.51
neriwo
However, the output is not being generated because of the error message that I am experiencing.
You had a syntax error in your case. More over you cannot mix datatypes so you need to cast digit to varchar or change '' i.e. to null.
select
person,
case
when digit >= 10 then ''
else cast(digit as varchar(20))
end 'digit'
from #table
Your case is not formatted correctly - here's one option -
(also, you can't select text and numbers in the same column - so I casted your number to text... tweak to fit your needs)
select
person,
case when digit >=10 then ''
else CONVERT(VARCHAR(10), digit)
end 'digit'
from #table

SQL Server CASE in ORDER BY clause in stored procedure

I have this ORDER BY clause here:
ORDER BY
CASE WHEN #isAlphabeticalSort = 1 THEN itemName ELSE itemId END
I have #isAlphabeticalSort defined in my stored procedure like so:
#isAlphabeticalSort bit = 1
When I run my stored procedure with #isAlphabeticalSort set to 0:
#isAlphabeticalSort = 0
It works as expected, when I set it to 1 when I run my stored procedure, I get this error:
Conversion failed when converting date and/or time from character string. Warning: Null value is eliminated by an aggregate or other SET operation.
I also have the red line under #isAlphabeticalSort = 0 says:
#isAlphabeticalSort is not a parameter in the procedure
My question is, am I defining my bool wrong? Is my case in my order by clause wrong? What am I doing wrong?
When using a CASE expression, the datatype that is attempted to be returned with be the datatype with the highest data type precedence. In this case you have 2 columns in your CASE expression itemName (which I assume is a varchar) and itemID (which I assume in an datetime). datetime has a higher precendence, so any return values will be implicitly converted to an datetime, if they aren't already.
The correct way, therefore, to do this would be:
ORDER BY CASE WHEN #isAlphabeticalSort = 1 THEN itemName END,
CASE WHEN #isAlphabeticalSort = 0 THEN itemId END, --As recommended by #JamesZ
[Other Columns];
For reference:
Data Type Precendence (Transact-SQL) and
CASE (Transact-SQL): Return Types
Both columns need to have the same type, you can try something like this
ORDER BY CASE WHEN #isAlphabeticalSort = 1 THEN itemName
ELSE CONVERT(varchar(10), itemId, 102) -- as recommended by Lamu
END
The error is due to your columns itemName (varchar ?) and itemId (int ?). You can only use the same datatype in Case statement.
https://learn.microsoft.com/en-us/sql/t-sql/language-elements/case-transact-sql#arguments
"The data types of else_result_expression and any result_expression must be the same or must be an implicit conversion."

CASE logic when removing NULLs

This is my first post, and I attempted to do a thorough search for this issue, so please accept my apologies if it has been posted elsewhere many times, but I'm wondering if anyone has encountered the following issue when attempting to remove NULLs from their result set:
case Occurrence
when NULL then '0'
else occurrence
end as Occurrence,
case Aggregate
when NULL then '0'
else Aggregate
end as Aggregate,
This didn't do anything to my NULLs; however, this did the trick:
case
when occurrence is NULL then '0'
else occurrence
end as Occurrence,
case
when aggregate is NULL then '0'
else Aggregate
end as Aggregate
Does anyone have any idea why this behaves this way? I'm using SQLServer2012.
I'm also not very versed in programming and only have less than a year SQL experience.
Thanks!
You should be using the ISNULL() or COALESCE() system function for handling nulls
something like
SELECT ISNULL(Occurrence , 0) AS Occurrence
,ISNULL(Aggregate , 0) AS Aggregate
FROM Table
OR
SELECT COALESCE(Occurrence , 0) AS Occurrence
,COALESCE(Aggregate , 0) AS Aggregate
FROM Table
The reason it didn't work in the case statement with
case Occurrence
when NULL then '0'
else occurrence
end as Occurrence,
is because it is interpreting it as
CASE
WHEN Occurrence = NULL THEN 0
ELSE Occurrence
END
Null is checked in sql server using IS NULL or IS NOT NULL if you use any other operator with null like = , <> or <, < it yields NULL hence the unexpected results.
Only for SQL Server 2012 and Later
In sql server 2012 and later versions you also have the IIF function
SELECT IIF(Occurrence IS NULL, 0, Occurrence) AS Occurrence
,IFF(Aggregate IS NULL , 0, Aggregate) AS Aggregate
FROM Table
You use simple case:
The simple CASE expression operates by comparing the first expression to the expression in each WHEN clause for equivalency. If these expressions are equivalent, the expression in the THEN clause will be returned.
Allows only an equality check.
case Occurrence
when NULL then '0'
else occurrence
end as Occurrence,
Which is executed as :
case
when occurence = NULL then '0'
else occurrence
end as Occurrence
Then expression occurence = NULL return NULL and is treated like False
Second your case use searched CASE with full condition and works fine:
case
when occurrence IS NULL then '0'
else occurrence
end as Occurrence,
So your question is about difference column IS NULL vs column = NULL
try
select 1 where null =null
select 1 where null is null
your statement looks like null equals null
select case when null is null then 1 else 0 end
select case null when null then 1 else 0 end
In your case use ISNULL this will give you the results your after
SELECT ISNULL(null,1)

Adding text string to CASE Statement

I am using the following SQL CASE:
SELECT
BomMast.BomStockCode
, BomMast.BomDescription
, CASE
WHEN StkItem.AveUCst <= 0 THEN 'ERROR'
WHEN StkItem.AveUCst > 0 THEN (StkItem.AveUCst * BomComp.ProductionQty)
END AS TotalCost
FROM BomComp
INNER JOIN BomMast
ON BomMast.BomID = BomComp.BomMasterKey
INNER JOIN StkItem
ON StkItem.StockLink = BomComp.ComponentStockLink
But I get the following message:
Msg 8114, Level 16, State 5, Line 2
Error converting data type varchar to float.
Am I not allowed to add test within the CASE statement?
Thank you!
Change your query to:
SELECT BomMast.BomStockCode
,BomMast.BomDescription
,CASE
WHEN StkItem.AveUCst <= 0
THEN 'ERROR'
WHEN StkItem.AveUCst > 0
THEN CAST((StkItem.AveUCst * BomComp.ProductionQty) AS NVARCHAR(MAX))
END AS TotalCost
FROM BomComp
INNER JOIN BomMast ON BomMast.BomID = BomComp.BomMasterKey
INNER JOIN StkItem ON StkItem.StockLink = BomComp.ComponentStockLink
The datatypes of the values you want to show in either branches of your CASE statements need to be the same in order to work.
Edit:
After #underscore_d's suggestion, I also consider that it would be a far better option to display NULL instead of the message ERROR and then handle this NULL value in the application level.
Hence, your case statement will change to:
CASE
WHEN StkItem.AveUCst <= 0
THEN NULL
WHEN StkItem.AveUCst > 0
THEN (StkItem.AveUCst * BomComp.ProductionQty)
END AS TotalCost
Yes, text can be used as the result a case statement, as can any datatype, but each case must return the same type, as the results column must have one type only.
Your [TotalCost] column has conflicting data types. [StkItem.AveUCst] is a float and the literal value of 'ERROR' is a varchar. If you are intending to retain the benefits of number-based value in your results column, consider replacing 'ERROR' with the SQL keyword NULL.
Your column TotalCost (neither any other column) can be a type-mixture. In first case it would be a varchar, in second case it would be floator something like that. THAT IS NOT POSSIBLE.