Smart CONVERT float to VARCHAR in T-SQL - sql

I have the following code
DECLARE #m FLOAT=213456789.55
DECLARE #sql VARCHAR(MAX)='INSERT INTO Test VALUES('+CONVERT(VARCHAR,#m,1)+')'
EXEC(#sql)
but the result is 213456790 instead of 213456789.55
When I try to write CONVERT(VARCHAR,213456789.55,1) it then returns 213456789.55 not 213456790
How do I solve this?
EDITS
Declaring #m as Decimal like following DECLARE #m DECIMAL(18,2)=213456789.55 solved the issue but I want to know if there is another solution for using float. Thanks

You can use STR instead of CONVERT. STR allows to specify number of decimal places to the right of the decimal point.
DECLARE #m FLOAT=213456789.55;
SELECT
#m AS [Float]
,CONVERT(VARCHAR(100),#m,0) AS Convert0
,CONVERT(VARCHAR(100),#m,1) AS Convert1
,CONVERT(VARCHAR(100),#m,2) AS Convert2
,LTRIM(STR(#m, 20, 2)) AS [Str]
Result (SQL Server 2008)
+--------------+--------------+----------------+------------------------+--------------+
| Float | Convert0 | Convert1 | Convert2 | Str |
+--------------+--------------+----------------+------------------------+--------------+
| 213456789.55 | 2.13457e+008 | 2.1345679e+008 | 2.134567895500000e+008 | 213456789.55 |
+--------------+--------------+----------------+------------------------+--------------+
CONVERT always uses scientific notation for float types.

try this:
DECLARE #m FLOAT=213456789.55
DECLARE #sql VARCHAR(MAX)='INSERT INTO Test VALUES('+CONVERT(VARCHAR,CAST(#m AS MONEY),1)+')'
EXEC(#sql)

Related

Convert Negative Varchar, Null to Decimal in SQL Server

I am trying to convert one of my measure column values having below from varchar to decimal(20,3). The 3rd value is a null value without any space and to make you understand I enclosed with quotes. I have tried with CAST but CAST is not able to change datatype as having negative sign. But I want to keep negative value.
I tried using TRY_CONVERT and TRY_CAST but that is not giving desired result. If anyone can help will be really helpful. I have tried below
CAST(COALESCE((NULLIF(SalesColumn,'')),'0') AS NUMERIC(20,12))
-992.0
0
I use SQL Server 2017 and CAST works just fine and maintains the "-"-sign, below is an example. Beware of the rounding, you might need to use ROUND() before converting it to decimal(20,3) by first converting it to a decimal with higher precision, using ROUND() and then casting it to decimal(20,3).
Using CAST to numeric or decimal works just fine on NULL as well.
DECLARE
#Val1 VARCHAR(10) = '-992.123'
,#Val2 VARCHAR(10) = '-45678'
,#Val3 VARCHAR(10) = NULL
,#Val4 VARCHAR(10) = ''
,#Val5 VARCHAR(10) = '321'
,#Val6 VARCHAR(10) = ' '
SELECT ISNULL(CAST(NULLIF(A, '') as decimal(20,3)), 0)
FROM (
VALUES (#Val1), (#Val2), (#Val3), (#Val4), (#Val5), (#Val6)
) Sub (A)
Which gives the result..
---------------------------------------
-992.123
-45678.000
0.000
0.000
321.000
0.000
(6 rows affected)
You can add another coalesce() within nullif() to handle null value. Please look into below examples.
declare #var as varchar(50);
set #var=null;
select cast(COALESCE((NULLIF(coalesce(trim(#var),0),'')),'0') AS NUMERIC(20,12))
GO
| (No column name) |
| ---------------: |
| 0.000000000000 |
declare #var as varchar(50);
set #var=' ';
select cast(COALESCE((NULLIF(coalesce(trim(#var),0),'')),'0') AS NUMERIC(20,12))
GO
| (No column name) |
| ---------------: |
| 0.000000000000 |
declare #var as varchar(50);
set #var='- 992 ';
select cast(COALESCE((NULLIF(coalesce(trim(#var),0),'')),'0') AS NUMERIC(20,12))
GO
| (No column name) |
| ----------------: |
| -992.000000000000 |
db<>fiddle here

Way of rounding of currency in SQL Server

Given the following values (float data type), I want to ROUND them in the following way:
+----------------+--------+
| Original Value | Result |
+----------------+--------+
| 53.36 | 53.40 |
| 53.34 | 53.30 |
| 53.35 | 53.35 | --Do not round up when 5
+----------------+--------+
Is there is a way to do this using T-SQL?
Since you need your value to remain xx.x5 when found but ROUND otherwise, the following will work for you:
(IIF available in SQL Server 2012+)
DECLARE #val FLOAT = 53.35;
SELECT IIF ((RIGHT(#val,1) = 5), #val, ROUND(#val,1)) result
SET #val = 53.34
SELECT IIF ((RIGHT(#val,1) = 5), #val, ROUND(#val,1)) result
SET #val = 53.36
SELECT IIF ((RIGHT(#val,1) = 5), #val, ROUND(#val,1)) result
Here is a good resource to read about differences of types, specifically read about float types. Seems that's possibly not a good datatype for the values you have. Just something to consider.

truncate integer

I got a task to chop an integer by 1 digit.
For example, If the new limit is 3 digits then 1234 will become 999 after the change. if the before change value is 12345 then it should becomes 999 after changes. if the pre-change value is 564 then it will remain unchanged.
This has to be done on Oracle as well as SQL server. the truc function only truncates decimal but not integer.
What is the best way to do this in SQL, PL/SQL or T-SQL?
Thanks in advance.
This works for T-SQL. Converting it to other sql dialects should just be as simple as finding the similar methods
declare #numDigits INT = 3;
declare #maxNumber INT = POWER(10,#numDigits)-1 -- gets "999" when using 3 digits, 9999 when using 4 etc
DECLARE #input INT = 1234
DECLARE #output INT = IIF(#input>#maxNumber,#maxNumber,#input)
SELECT #output -- selects 999
Oracle does have the POWER function, but does not have the ternary/IIF function
You could use case statements for this like:
SELECT CASE [yourInt] >= 1000 THEN 999 ELSE [yourInt] END AS 'UpperLimit'
From [YouTable]

Replace non-numeric characters with numbers

I have a column that looks like:
Column A
1A
2B
5Z
Essentially, I need to replace the letter part with the correspending number in the alphabet. LIke:
Column A
1.1
2.2
5.26
I was thinking of creating a "lookup" table to retrieve the correspnding letter number but wanted to see if there is a more elegant/efficient way?
Many thanks
Just give you an algorithm to convert character to number and let parsing characters within a column up to you:
DECLARE #offset int
SET #offset = 64
DECLARE #character char
-- OUTPUT | A | 1 |
SET #character = 'A'
SELECT #character, ASCII(#character) - #offset
-- OUTPUT | Z | 26 |
SET #character = 'Z'
SELECT #character, ASCII(#character) - #offset

Is there any simple way to format decimals in T-SQL?

I know it could be done trivially in a non-SQL environment [post-data processing, frontend, what have you], but that's not possible at the moment. Is there a way to take a decimal(5,2) and convert it to a varchar without the trailing zeroes/decimal points? For example:
declare #number decimal(5,2)
set #number = 123.00
select cast(#number as varchar) as FormattedNumber
And the result is '123.00'. Is there a (simple) way to get '123' instead? And likewise, instead of '123.30', '123.3'? Could do it by figuring out whether or not the hundredths/tenths places were 0 and manually trimming characters, but I wanted to know if there was a more elegant solution.
What about:
SELECT CAST(CAST(#number AS float) AS varchar(10))
However you may want to test this carefully with your raw data first.
This way is pretty simple:
DECLARE #Number DECIMAL(5,2)
SELECT #Number = 123.65
SELECT FormattedNumber = CAST(CAST(#Number AS DECIMAL(3,0)) AS VARCHAR(4))
Returns '124'.
The only thing to consider is whether you want to round up/down, or just strip the zeroes and decimal points without rounding; you'd cast the DECIMAL as an INT in the second case.
For controlled formatting of numbers in T-SQL you should use the FORMAT() function. For example:
DECLARE #number DECIMAL(9,2); SET #number = 1234567.12;
DECLARE #formatted VARCHAR(MAX); SET #formatted = FORMAT(#number, 'N0', 'en-AU');
PRINT #formatted;
The result will be:
1,234,567
The arguments to the FORMAT() function are:
FORMAT(value, format [, culture])
The value argument is your number. The format argument is a CLR type formatting string (in this example, I specified "normal number, zero precision"). The optional culture argument allows you to override the server culture setting to format the number as per a desired culture.
See also the MSDN ref page for FORMAT().
The Convert function may do what you want to do.
ms-help://MS.SQLCC.v9/MS.SQLSVR.v9.en/tsqlref9/html/a87d0850-c670-4720-9ad5-6f5a22343ea8.htm
Let me try this again....
CREATE FUNCTION saneDecimal(#input decimal(5,2)) returns varchar(10)
AS
BEGIN
DECLARE #output varchar(10)
SET #output = CAST(#input AS varchar(10))
DECLARE #trimmable table (trimval char(1))
INSERT #trimmable VALUES ('0')
INSERT #trimmable VALUES ('.')
WHILE EXISTS (SELECT * FROM #trimmable WHERE trimval = CAST(SUBSTRING(#output, LEN(#output), 1) AS char(1)))
SET #output = LEFT(#output, LEN(#output) - 1)
RETURN #output
END
GO
SELECT dbo.saneDecimal(1.00)
You could strip the trailing zeroes in a while loop:
declare #number decimal(5,2)
declare #str varchar(100)
set #number = 123.00
set #str = #number
while substring(#str,len(#str),1) in ('0','.',',')
set #str = substring(#str,1,len(#str)-1)
But as AdaTheDev commented, this is more easily done client-side.
Simple and elegant? Not so much...but that's T-SQL for you:
DECLARE #number decimal(5,2) = 123.00
DECLARE #formatted varchar(5) = CAST(#number as varchar)
SELECT
LEFT(
#formatted,
LEN(#formatted)
- PATINDEX('%[^0.]%', REVERSE(#formatted))
+ 1
)
Use the Format(value,format string,culture) function in SQL Server 2012+
If you have SQL Server 2012 or Greater you can use the format function like this:
select format(#number,'0') as FormattedNumber
Of course the format function will return an nvarchar, and not a varchar. You can cast to get a specific type.
Also, take a look at the T-SQL STR function in Books Online; this can be used for formatting floats and might work for your case. For some reason it doesn't come up in Google searches relating to this problem.