sql server decimal formatting in query string - sql-server-2005

I've found several solutions online, but none that really do what I'm looking for. So, here goes..
I have several columns in my table of type numeric(8, 4), numeric(8, 5), etc, and when I retrieve the data it comes with all the trailing 0's. Is there a way I can format it so it leaves off all the trailing and leading 0's? I don't want to specify a length of precision. Here's some examples of what I'm looking for:
145.5000 -> 145.5
145.6540 -> 145.654
73.4561 -> 73.4561
37.0000 -> 37
Thank you much!

Float and real are both approximate data types so this may not work with every value you come across. Given that you only have 4 or 5 digits of precision, I think this method will always work, but you'll want to test it pretty well before implementing this in to production.
DECLARE #d DECIMAL(8,5)
select #d = 5.12030
Select Convert(Float, #d)

Ideally you want to do this in front-end code
so how will you distinguish between 0.37 and 37.0 if all you want is 37?
Here is one way in SQL
Replace 0 with space and do trim and then replace space back to 0
example
edit: missed the trailing dot before..added that as a case statement
DECLARE #d DECIMAL(8,5)
select #d = 5.12030
SELECT CASE WHEN RIGHT(REPLACE(RTRIM(LTRIM(REPLACE(CONVERT(VARCHAR(100),#d),'0',' '))),' ','0'),1) = '.'
THEN REPLACE(REPLACE(RTRIM(LTRIM(REPLACE(CONVERT(VARCHAR(100),#d),'0',' '))),' ','0'),'.','')
ELSE
REPLACE(RTRIM(LTRIM(REPLACE(CONVERT(VARCHAR(100),#d),'0',' '))),' ','0') END

Related

Always include right most 6 digits, but allow for more digits if they aren't leading zeroes?

This may sound like a weird request, but I have to make an excel sheet with EXACTLY the same format as their old sheet. The values in the column in question will be a numeric code. I need to display up to 8 digits, and no less than 6 digits. The code will only be 7 or 8 digits if the first number in the sequence is not zero. If there are 6 digits or less, I need to display 6 digits including leading zeroes. Here is an example:
The data comes in like this:
000023547612
000000873901
000031765429
000000000941
000000055701
I need those numbers to display as:
23547612
873901
31765429
000941
055701
Is there a way to achieve this in a SQL statement?
You can check the length of the string and use right to pad it. But GSerg's answer is better.
declare #Test table (Number varchar(12))
insert into #Test (Number)
values ('000023547612'),('000000873901'),('000031765429'),('000000000941'),('000000055701')
select Number
, case when len(convert(varchar(12), convert(int, Number))) <= 6 then right('000000'+convert(varchar(12), convert(int, Number)),6) else convert(varchar(12), convert(int, Number)) end
, format(convert(int, Number), N'##000000') -- GSerg's Answer
from #Test
Returns:
Number Attempt1 Attempt2 (GSerg)
000023547612 23547612 23547612
000000873901 873901 873901
000031765429 31765429 31765429
000000000941 000941 000941
000000055701 055701 055701
PS: In future if you provide test data in this format (table variable or temp table) you will make it much easier for people to answer.
You can use
SELECT Substring('0078956', Patindex('%[^0 ]%', '0078956' + ' '), Len('0078956') ) AS Trimmed_Leading_0;

How many ways can you generate an error converting varchar to numeric that won't be caught by ISNUMERIC()?

I am in the process of loading a bunch of tables into SQL Server and converting them from varchar to specific data types (int, date, etc.). One frustration is how many different ways there are to break the conversion from string to numeric (int, decimal, etc) and that there is not an easy diagnostic tool to find the offending rows (besides ISNUMERIC() which doesn't work all the time).
Here is my list of ways to break the conversion that won't get caught by ISNUMERIC().
The string contains scientific notation (ie 3.55E-10)
The string contains a blank ('')
The string contains a non-alphanumeric symbol ('$', '-', ',')
Here's what I'm currently using to compensate:
SELECT
CASE
WHEN [MyColumn] IN ('','-') THEN NULL -- deals with blanks
WHEN [MyColumn] LIKE '%E%' THEN CONVERT(DECIMAL(20, 4), CONVERT(FLOAT(53), [MyColumn])) -- deals with scientific notation
ELSE CAST(REPLACE(REPLACE([MyColumn] , '$', ''), '-', '') AS DECIMAL(20, 4))
END [MyColumn] -- deals with special characters
FROM
MyTable
Does anyone else have others? Or good ways to diagnose?
Don't use ISNUMERIC(). If you are on 2012+ then you could use TRY_CAST or TRY_CONVERT.
If you are on older versions, you could use some syntax like this:
SELECT *
FROM #TableA
WHERE ColA NOT LIKE '%[^0-9]%'
You can try to use LIKE '%[0-9]%' instead of ISNUMERIC()
SELECT col, CASE WHEN col NOT LIKE '%[^0-9]%' and col<>''
THEN 1
ELSE 0
END
FROM T
You can use NOT LIKE to exclude anything that isn't a digit... and REPLACE for commas and periods. Naturally, you can add other nested REPLACE functions for values you want to accept.
declare #var varchar(64) = '55,5646'
SELECT
CASE
WHEN replace(replace(#var,'.',''),',','') NOT LIKE '%[^0-9]%'
THEN 1
ELSE 0
END
This allows you to accept decimals for your decimal / numeric / float conversions.

Need to pad zeros left and right for a string value according to decimal format

So if I have a data (varchar) like say 10.1
I need the value as 0000101000000.
means (000010) whole number and (1000000) decimal value.
Its a 13 character string ,numbers coming before decimal point should be in first 6 characters and numbers coming after decimal point should be in last 7 characters
Maybe..?
DECLARE #d decimal(13,7) = 10.1;
SELECT RIGHT('0000000000000' + CONVERT(varchar(13),CONVERT(bigint,(#d * 10000000))),13);
Using my crystal ball here though.
Edit: As, for some reason, the OP is storing a decimal as a varchar (this is a really bad bad idea on it's own), I have added further logic to attempt to convert the value to a decimal first.
As experience has taught many of us, give a user a non-numeric column to store a numeric value in and they're more than happily store a non-numeric value in it, so i have used TRY_CONVERT and assumed you are using SQL Server 2012+:
DECLARE #d varchar(13) = 10.1;
SELECT RIGHT('0000000000000' + CONVERT(varchar(13),CONVERT(bigint,(TRY_CONVERT(decimal(13,7),#d) * 10000000))),13);
SELECT REPLICATE('0',6-LEN(SUBSTRING(CAST([data] AS VARCHAR), 1,
CHARINDEX('.',CAST([data] AS VARCHAR)) -1)))+SUBSTRING(CAST([data] AS VARCHAR), 1,
CHARINDEX('.',CAST([data] AS VARCHAR)) -1)+
SUBSTRING(CAST([data] AS VARCHAR), CHARINDEX('.',CAST([data] AS VARCHAR)) + 1,
LEN(CAST([data] AS VARCHAR)))+REPLICATE('0',7-LEN(SUBSTRING(CAST([data] AS VARCHAR), CHARINDEX('.',CAST([data] AS VARCHAR)) + 1,
LEN(CAST([data] AS VARCHAR))))) AS Whole
FROM Table1
Output
Whole
0000101000000
Demo
http://sqlfiddle.com/#!18/8649d/16
You can use some math and string operations to do it like below
see live demo
declare #var decimal(10,4)
set #var=10.1
select #var,
right(cast(cast(( floor(#var)+ power(10,7)) as int) as varchar(13)),6)
+
cast(cast(((#var- floor(#var)) * power(10,7)) as int) as varchar(13))
There's a fair amount of string manipulation to be done here. I'll step through what I did.
I used a variable for the base number so I could verify different results:
declare #n decimal(9,3) = 10.1
You need 6 spaces left of the decimal and 7 spaces to the right, so I'm doing all the manipulation on a VARCHAR(13). I didn't create a new variable as a VARCHAR because I'm assuming you want to be able to do this conversion in line on the fly, so I'm using that CAST over and over again.
Start by finding the decimal place.
SELECT CHARINDEX('.',CAST(#n as VARCHAR(13)))
In the sample number, that's a 3, but it could obviously change.
Now, get the portion of the number to the left of the decimal place.
SELECT SUBSTRING(CAST(#n as VARCHAR(13)),1,CHARINDEX('.',CAST(#n as VARCHAR(13)))-1)
Then get the portion to the right of the decimal.
SELECT SUBSTRING(CAST(#n as VARCHAR(13)),CHARINDEX('.',CAST(#n as VARCHAR(13)))+1,LEN(CAST(#n as VARCHAR(13))))
Pad the leading zeroes. Put 6 on, concatenate, and take a RIGHT 6. Accounts for no digits to the left of the decimal.
SELECT RIGHT(REPLICATE(0,6) + SUBSTRING(CAST(#n as VARCHAR(13)),1,CHARINDEX('.',CAST(#n as VARCHAR(13)))-1), 6)
Pad the trailing zeroes. Same idea, but in the other direction.
SELECT LEFT(SUBSTRING(CAST(#n as VARCHAR(13)),CHARINDEX('.',CAST(#n as VARCHAR(13)))+1,LEN(CAST(#n as VARCHAR(13)))) + REPLICATE(0,7),7)
Then put it all together.
SELECT RIGHT(REPLICATE(0,6) + SUBSTRING(CAST(#n as VARCHAR(13)),1,CHARINDEX('.',CAST(#n as VARCHAR(13)))-1), 6)
+
LEFT(SUBSTRING(CAST(#n as VARCHAR(13)),CHARINDEX('.',CAST(#n as VARCHAR(13)))+1,LEN(CAST(#n as VARCHAR(13)))) + REPLICATE(0,7),7)
Results.
0000101000000
declare #var varchar(20) = '10000.112'
SELECT FORMAT (FLOOR(#var), '000000') + left((PARSENAME(#var,1)) + replicate('0',7),7)

I'm trying to convert a base 10 number in sql to base 2 / binary but what's being returned ins't ones and zero's

I'm just using some simple sql to try and get it working and then I will implement it into my program.
So my code is below:
select convert(varbinary(16), cast('63' as int)))
My result from this query is 0x000003F which is not what I wanted, I was expecting 000111111.
Does anyone know why it does this and how I can get it to display the number as 1's and 0's, it would be greatly appreciated, Thanks. This is using MSSql.
In MSSQL I think you could try this:
DECLARE #var1 AS int;
SET #var1=12;
WITH A AS (
SELECT 0 AS ORD, #var1 AS NUMBER, CAST('' AS VARCHAR(20)) AS BITS
UNION ALL
SELECT ORD+1, NUMBER/2, CAST(BITS+CAST(NUMBER%2 AS VARCHAR(20)) AS VARCHAR(20))
FROM A
WHERE NUMBER>0)
SELECT RIGHT('000000000000000'+ CASE WHEN BITS='' THEN '0' ELSE REVERSE(BITS) END,16) AS BIN_VALUE
FROM A
WHERE NUMBER=0;
Ouput:
BIN_VALUE
0000000000001100
As collapsar notes in MySQL, you need to specify base 2, which is what you are missing here. Without that, MySQL defaults to hexadecimal encoding here but you need to provide a number (63), a starting base (10), and a final base (2).
Putting this together you get select conv(63, 10, 2) sqlfiddle

Removing Leading Zeros Part 2

SQL Server 2012
I have 3 columns in my table that will be using a function. '[usr].[Udf_OverPunch]'. and substring.
Here is my code:
[usr].[Udf_OverPunch](SUBSTRING(col001, 184, 11)) as REPORTED_GAP_DISCOUNT_PREVIOUS_AMOUNT
This function works appropriately for what I need it to do. It is basically converting symbols or letters to a designated number based on a data dictionary.
The problem I am having is that there are leading zeros. I just asked a questions about leading zeroes but it won't allow me to do it with the function columns because of the symbols cannot be converted to int.
This is what I am using to get rid of leading zeros (but leave one zero) in my code for the other columns:
cast(cast(SUBSTRING(col001, 217, 6) as int) as varchar(25)) as PREVIOUS_REPORTING_PERIOD
This works well at turning a value of '000000' to just one '0' or a value of '000060' to '60' but will not work with the function because of the symbol or letter (when trying to convert to int).
As I mentioned, I have 3 columns which produce values that look something like this when the function is not being used:
'0000019753{'
'0000019748G'
'0000019763H'
My goal here is to use the function while also removing the leading zeros (unless they are all zeros then keep one zero).
This is what I attempted that isn't working because the value contains a character that isn't an integer:
[usr].[Udf_OverPunch]cast(cast(SUBSTRING(col001, 184, 6) as int) as varchar(25)) as REPORTED_GAP_DISCOUNT_PREVIOUS_AMOUNT,
Please let me know if you have any ideas or need more information. :)
select case when col like '%[^0]%' then substring(col,patindex('%[^0]%',col),len(col)) when col like '%0%' then '0' else col end
from tab
or
select case when col like '%[^0]%' then right(col,len(ltrim(replace(col,'0',' ')))) when col like '%0%' then '0' else col end
from tab
I am handling such replacement with T-SQL CLR function that allows replacement using regular expressions. So, the solution will be like this:
[dbo].[fn_Utils_RegexReplace] ([value], '^0{1,}(?=.)', '')
You need to create such function because there are no regular expression support in T-SQL (build-in).
How to create regex replace function in T-SQL?
For example:
try this,
declare #i varchar(50)='0000019753}'--'0000019753'
select case when ISNUMERIC(#i)=1 then
cast(cast(#i as bigint) as varchar(50)) else #i end
or
[usr].[Udf_OverPunch]( case when ISNUMERIC(col001)=1 then
cast(cast(col001 as bigint) as varchar(50)) else col001 end)