"Error converting data type nvarchar to float" with CASE WHEN Statement - sql

I'm trying to run a query with the following as one of the select statements, and I keep getting the error "Error converting data type nvarchar to float." I've been converting VBA IIf statements to CASES and I can't seem to get the conversions right. fld2 is nvarchar(15) and fld1 is a float data type. I need help pinpointing why this error is being thrown.
CASE WHEN (IsNumeric([fld2]) = 1) THEN Round(Convert(nvarchar,[fld2]) +
' / ' + Convert(nvarchar,[fld1]),(Len(Convert(nvarchar,[theData])) -
Charindex(Convert(nvarchar, [fld2]),'.'))) ELSE [fld2] END,

As is, your example would produce quite a funny expression for SQL server to evaluate. Let's substitute values for fld1, fld2, and theData as an example to see what you're trying to do:
[fld1] = 42.0
[fld2] = N'69.56'
[theData] = N'something'
(an N before a string makes it an nvarchar instead of varchar)
With substitutions, the resulting query would look like this:
CASE WHEN (IsNumeric(N'69.56') = 1) THEN
Round(Convert(nvarchar,'69.56') + ' / ' + Convert(nvarchar, 42.0),
(Len(Convert(nvarchar,'something')) - Charindex(Convert(nvarchar, N'69.56'),'.')))
ELSE
N'69.56'
END
Since you don't need to convert an nvarchar to nvarchar explicitly, your query actually looks more like:
CASE WHEN (IsNumeric(N'69.56') = 1) THEN
Round(N'69.56 / ' + Convert(nvarchar, 42.0),
(Len(N'something') - Charindex(N'69.56','.')))
ELSE
N'69.56'
END
So there are a couple of problems:
You're passing a varchar value into the ROUND() function, which expects a numeric value, not an expression
The two paths of the CASE statement are returning different types
What I think your query should look like is:
CASE WHEN IsNumeric([fld2]) = 1 THEN
CONVERT(nvarchar, ROUND(CONVERT(float, [fld2]) / [fld1],
(LEN([theData]) - CHARINDEX([fld2], '.'))))
ELSE
[fld2]
END
The above does the math and rounding on numeric results instead of strings, doesn't do any unnecessary conversions, and also returns the same type in both cases.

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

CAST(somenumber as VARCHAR(10)) + somestring returns Error converting data type varchar to numeric

I'm trying to combine a min and max salary with a hyphen for display in a report. I feel like I've done this a hundred times but I still can't figure out why I'm getting the "Error converting data type varchar to numeric" especially since I'm trying to convert a numeric to varchar not the other way around.
amt_exp_formatted = CASE
WHEN a.class_code IN ('9997','9998','9999') THEN 0
--ELSE CAST(e.min_sal as VARCHAR(10)) + '-' + CAST(e.max_sal as VARCHAR(10))
ELSE CONVERT(VARCHAR(1), 1) + CONVERT(VARCHAR(1), 'a')
END
In the above example if I use 'a' I get the error. If I change 'a' to '9' then it works AND it appends 9 to the 1 (i.e. 19) rather than adding them together which is exactly what I want but with a character string. I've tried both CAST and CONVERT with no luck. I know I shouldn't need the second CONVERT on the letter 'a' but I was just trying to force the data types to be the same just in case. I have no doubt at all I'm missing something simple but I can't seem to get it so I figured it wouldn't hurt to ask the community.
Thank you!
A case expression returns one value with a determinate type. If any returned fork returns a number, then number it is. And strings get converted.
So, be sure you are returning a string in all cases:
(CASE WHEN a.class_code IN ('9997', '9998', '9999')
THEN '0'
ELSE CONCAT(e.min_sal, '-', e.max_sal)
END)
CONCAT() automatically converts the arguments to strings.
This is becuase you are mixing the data type. in the first part of case you were returning 0 while in the else part you're converting it to varchar(). - you can try the below returning 0 as also varchar
amt_exp_formatted = CASE
WHEN a.class_code IN ('9997','9998','9999') THEN '0'
--ELSE CAST(e.min_sal as VARCHAR(10)) + '-' + CAST(e.max_sal as VARCHAR(10))
ELSE CONVERT(VARCHAR(1), 1) + CONVERT(VARCHAR(1), 'a')
END

Matching two values of different types in two SQL databases

I am trying to compare records between two different SQL tables/databases in my Node project and have to do some transformation in order to compare the values.
In one database (MariaDB) the value is of type INT, and looks like this: 516542
In the other (SQL Server) database the value I need to match to is of type char(21), and looks like this: 00000516542-000
What I tried doing was this:
WHERE (REPLACE(LEFT( LM301.DOCNUMBR, CHARINDEX('-', LM301.DOCNUMBR)), '-', '')) = 516542
This works for some records, but for others I get this error:
"The conversion of the varchar value '0004000009123' overflowed an int
column."
If I pass the first value in as a string ('516542') it doesn't match at all.
How can I handle this scenario?
The error you're getting is at least correct. But from your example i can't determine whether the conversion is right or not.
Basically, somewhere in your CHAR(21). There a value which is greater than int32, or SQL Server int type, in value. This value is: 2,147,483,648. 4,000,009,123 is greater than this max value as specified by the error message.
The DBMS, with this where statement, will try to do the operation and compare to all records, and it runs into an overflow. You could do a string compare instead. Or try an explicit conversion and convert it to bigint.
WHERE CONVERT(BIGINT, (REPLACE(LEFT( LM301.DOCNUMBR, CHARINDEX('-', LM301.DOCNUMBR)), '-', ''))) = 516542
It's doing an implicit cast to INT because that's your compare type, then overflows. Making the conversion explicit allows you to determine the datatype instead.
Basically what's happening:
IF ('21474836480' >= 100) --Implicit conversion: Error and prints false
PRINT 'True'
ELSE
PRINT 'False'
IF ('214748364' >= 100) --Implicit Conversion: True
PRINT 'True'
ELSE
PRINT 'False'
IF (CONVERT(BIGINT, '21474836480') >= 100) --Explicit Conversion: Prints True
PRINT 'True'
ELSE
PRINT 'False'
So wrapping your value in an explicit conversion should resolve your error.
You need to do explicit type conversation with TRY_CONVERT():
TRY_CONVERT(BIGINT, LEFT(LM301.DOCNUMBR, CHARINDEX('-', LM301.DOCNUMBR + '-') - 1)) = 516542
TRY_CONVERT() will return NULL if conversation fail.
You don't need to use replace(), you can subtract the position.
EDIT : Try_CONVERT() is available from 2012 +. For older version you can do :
(CONVERT(BIGINT, LEFT(LM301.DOCNUMBR, CHARINDEX('-', LM301.DOCNUMBR) - 1)) = 516542 AND
CHARINDEX('-', LM301.DOCNUMBR) > 0)
)
Note : This might fail if DOCNUMBR doesn't have numeric value prior to -.

Conversion failed when adding percentage to end of value

,CASE WHEN
sq.Total_Sales > 0 THEN
CAST(ROUND(CAST(sq.Total_Sales AS FLOAT) / (SUM(pfm.C1)) * 100,0) AS varchar(10)) + '%'
ELSE 0
END AS Conversion_Rate
Please can someone help with why I am unable to add % at the end?
I am getting a "conversion failed when converting the varchar value '25%' to data type int" error.
Example data:
So a column returned from a query can only be of a single type, right? When looking at your query, the db engine sees two types in the CASE statement:
CAST(ROUND(CAST(sq.Total_Sales AS FLOAT) / (SUM(pfm.C1)) * 100,0) AS varchar(10)) + '%' produces VARCHAR(11)
0, in the ELSE part, is an INT
The database engine tries to consolidate them both to INT, and since '5%' can't be casted to an INT, you get an error. You need to change your ELSE 0 to something producing a varchar, like ELSE '0%' or even ELSE ''.
It appears SQL Server does not approve of your attempt to potentially use the integer literal 0 in a string concatenation. Whether or not this would or could actually happen is another story. It matters not, as SQL Server will require you to use strings to concatenate strings--even when the theoretical path to concatenation is not possible.
Try this:
,CASE WHEN
sq.Total_Sales > 0 THEN
CAST(ROUND(CAST(sq.Total_Sales AS FLOAT) / (SUM(pfm.C1)) * 100,0) AS varchar(10)) + '%'
ELSE '0'
END AS Conversion_Rate

SQL Server SELECT To Return String Including Single Quotes

I need to get a formatted string with data from a SELECT statement. The problem is that I need it to return with single quotes. Here's an example.
I have a table that contains 2 columns TrainingSwipeID (int) and ExtendedDate (datetime). For an example I have a row in the table that contains
TrainingSwipeID = 123
TrainingEnd = 04/23/2019 09:00:00
I need to create a SELECT statement that will return the formatted string such as
{'TrainingSwipeID':123,'TrainingEnd ':04/23/2019 09:00:00}
I've researched and found that you can double single quote to get around this issue. I've tried the following with no luck and I get the following error "Conversion failed when converting the varchar value '{'TrainingSwipeID':' to data type int."
SELECT '{''TrainingSwipeID'':' + TrainingSwipeID + '''TrainingEnd'':' + TrainingEnd + '}'
AS MyFormattedString
FROM TrainingSwipe
Can anyone help?
The numeric and date/time data types have a higher precedence than the string data types. That's why you need to convert the numeric types into strings and prevent undesired implicit conversions.
SELECT '{''TrainingSwipeID'':' + CAST(TrainingSwipeID AS varchar(15))
+ '''TrainingEnd'':' + CONVERT( varchar(20), TrainingEnd , 101) + ' '
+ CONVERT( varchar(20), TrainingEnd , 8) + '}'
AS MyFormattedString
FROM TrainingSwipe
I finally used the simplest answer from #AlexKudryashev but Luis' answer worked as well.
SELECT CONCAT('{''TrainingSwipeID'':' , TrainingSwipeID, ',''TrainingEnd'':', TrainingEnd, '}')