sql inconsistent datatypes: expected number got char - sql

I am trying to write a Case When statement, but I get an inconsistent datatypes error. I need 'Returned' displayed if the first when statement is not met.
CASE
WHEN (X.RECEIVED_QTY = 0) THEN FLOOR(SYSDATE-INVENTORY_TRANS.TRANSACTION_DATE)
WHEN (X.RECEIVED_QTY = 0) THEN 'RETURNED'
END AS DAYS_OUT

You can't mix results of a CASE statement, that means you can't return an INT under one condition and a VARCHAR in another. If you want to return Returned then you will need to CONVERT or CAST your numeric values to VARCHAR
You also have a syntactical problem with your CASE.
You'd have to change it to something like this:
CASE X.RECEIVED_QTY
WHEN 0 THEN CAST( FLOOR(SYSDATE-INVENTORY_TRANS.TRANSACTION_DATE) AS VARCHAR(20))
ELSE 'RETURNED'
END AS DAYS_OUT

Related

Error converting varchar value to data type int

I am trying to concatenate two integer values with hyphen in between. So when I try to do the same, SQL gives me the error.
Conversion failed when converting the varchar value '30-45' to data type int.
NOTE:
Also, the second value for concatenation can be null so in that case, a hyphen should not be concatenated.
example
from1 = 30
to1 = 45
case
to1 is null
then from1
else CONCAT(from1, '-' + nullif(to1,'')) end
AS age
//This works but shows 3045 instead of 30-45.
concat(from, '-', to) AS age
//This doesn't work out as it gives the error 'Conversion failed when converting the varchar value '30-45' to data type int.'
Thanks for the help in advance and looking forward to it.
DECLARE #FROM INT=30;
DECLARE #TO INT=45;
SELECT CAST(#FROM AS VARCHAR(2))+'-'+CAST(ISNULL(#TO,'') AS VARCHAR(2));
SQL is trying to convert your phrase to int probably because it's part of CASE statement. It uses the first route to determine the output type.
In your case- you put NULL as the first route option in your CASE, so it is determined as int. try putting instead of it this: CAST(NULL AS VARCHAR(10))
It seems that for some reason you think that strings that contain mathematical expressions are resolved as said expression, not an as literal string. Thus if you have the varchar value '30-45' you think it'll return the int value -15; this isn't true. This in fact isn't true in any language, let alone T-SQL.
For what you have, in your ELSE the '-' isn't a minus... It's a string... - is a minus. If you want to substract a number from another then it's a basic maths expression: a - b. You're effectively doing CONVERT(varchar,a) + '-' + CONVERT(varchar,b)... Just have your ELSE as the following:
from1 - NULLIF(to1,0)
This will return NULL if from1 has the value NULL, or to1 has the value NULL or 0.
Please check below code. It's working
example
#from1 = 30
#to1 = 45
IF #to1 is null
SELECT #from1
ELSE
SELECT CONCAT(#from1, '-' , nullif(#to1,'')) as age

Using SUM in CASE if value is numeric

I have a similar situation to the CASE clause well known problem:
DECLARE #i INT = 1;
SELECT CASE WHEN #i = 1 THEN 1 ELSE MIN(1/0) END;
In that case the code will throw an exception, Divide by zero error encountered, even though in theory you would never reach that min(1/0) scenario.
So I have similar situation:
CASE WHEN CodeValue in ('Numeric1','Numeric2') THEN SUM(cast(VarcharValue as int)) ELSE max(VarcharValue) END
In other words I need to use SUM function if VarcharValue is numeric (it could be determined by CodeValue if it is numeric), if that's not the case, I need return VarcharValue with MAX function.
Any suggestions?
You have a strange construct, because one case branch returns a string and another a number. SQL Server decides, in such a case, that the expression returns a number.
And you'll have problems with the ELSE, because a non-numeric string will be converted to a number. Error.
The following might work:
(CASE WHEN CodeValue in ('Numeric1', 'Numeric2')
THEN CAST(VARCHAR(MAX), SUM(CAST(VarcharValue as int)))
ELSE MAX(VarcharValue)
END)
You might still have a problem, if the SUM() is being calculated over all data before filtering (which I think is possible with an aggregation query). My recommendation is to upgrade to a supported version of SQL Server and use:
(CASE WHEN CodeValue in ('Numeric1', 'Numeric2')
THEN CAST(VARCHAR(MAX), SUM(TRY_CAST(VarcharValue as int)))
ELSE MAX(VarcharValue)
END)
However, you can repeat the CASE logic:
(CASE WHEN CodeValue in ('Numeric1', 'Numeric2')
THEN CAST(VARCHAR(MAX), SUM(CASE WHEN CodeValue in ('Numeric1', 'Numeric2') THEN CAST(VarcharValue as int) END))
ELSE MAX(VarcharValue)
END)

TSQL CASE unexpectedly processing multiple THEN statements

I have a simple SQL CASE statement that I am trying to interpret the datatype of a variable and then converting it to said format. I have the following sample:
DECLARE #P1 varchar(10) = '2';
SELECT CASE 1
WHEN ISNUMERIC(#P1) THEN (CAST(#P1 AS INT))
WHEN ISDATE(#P1) THEN (CAST(#P1 AS DateTime))
ELSE 'N' END AS Test2P1
I would expect it to return an integer value of 2. However, this is what I get.
Test2P1
1900-01-03 00:00:00.000
However, if I modify the code to just display a character instead of CASTING the variable, I get a different result:
DECLARE #P1 varchar(10) = '2';
SELECT CASE 1
WHEN ISNUMERIC(#P1) THEN 'I'
WHEN ISDATE(#P1) THEN 'D'
ELSE 'N' END AS Test2P1
Then I get a result of: I
Taking this experiment one step further, if I leave the first test returning an 'I' but casting the date, then I get an error:
DECLARE #P1 varchar(10) = '2';
SELECT CASE 1
WHEN ISNUMERIC(#P1) THEN 'I'
WHEN ISDATE(#P1) THEN (CAST(#P1 AS DateTime))
ELSE 'N' END AS Test2P1
Msg 241, Level 16, State 1, Line 3
Conversion failed when converting date and/or time from character string.
It appears that SQL is evaluating multiple instances of THEN statements. However, the ISDATE expression does NOT return true. I am stumped.
In my research, I came across this article [SQL Performance] (https://sqlperformance.com/2014/06/t-sql-queries/dirty-secrets-of-the-case-expression) What he is saying in this article makes complete sense. But I do not see where it applies in this situation as I am never changing the value of the variable.
I have also wrapped my CASE statement in COALESCE(), but it does not appear to help. I wouldn't have expected it to, but I found multiple articles referencing this as a solution to similar problems. This seems like a very simple CASE statement, but I do not know where I am going wrong. Any help is greatly appreciated.
DateTime has a higher datatype precedence in SQL Server than INT does, so your whole CASE is getting cast as DATETIME. You can only return data of a single datatype in one column, thus the need for datatype precedence.
Here is the MSDN article showing precedence.
Although I can't think of a good reason to do this, you could force the case expression to return sql_variant, which can store multiple different types, eg:
DECLARE #P1 varchar(10) = '2';
SELECT CASE 1
when 0 then cast(null as sql_variant)
WHEN ISNUMERIC(#P1) THEN (CAST(#P1 AS INT))
WHEN ISDATE(#P1) THEN (CAST(#P1 AS DateTime))
ELSE 'N' END AS Test2P1

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 statement fails with data conversion error

I have a integer column in which i need to add a case statement to display in a report. If that int column = -1 , the data in that column should be DOWN else the int value / 100
If i try like below
CASE WHEN LOADVALUE = -1 then 'DOWN'
ELSE LOADVALUE/100 END
As expected, i'm receiving an error : Error converting varchar to int. Please help.
You need to cast your ELSE result to a VARCHAR
CASE WHEN LOADVALUE = -1 THEN 'DOWN'
ELSE CONVERT(VARCHAR (10), LOADVALUE/100) END
Something you should keep in mind though, is that since the datatype of LOADVALUE is an INT, you may get unexpected results due to integer division. You may want to consider using this instead:
CASE WHEN LOADVALUE = -1 THEN 'DOWN'
ELSE CONVERT(VARCHAR (10), (LOADVALUE * 1.0)/100.0) END
This will convert the LOADVALUE to a decimal to correctly do the division.
(Please disregard this alternative if you are actually wanting integer division)
When you use case make sure, the datatypes in when clause and else clauses are consistent.
CASE WHEN LOADVALUE = -1 then 'DOWN'
ELSE cast(LOADVALUE/100 as varchar) END