Splitting field and adding decimal point to create numeric value SQL - sql

I have a field in SQL Server 2014 that I am working with that looks like this:
**RawField**
20060202
20060323
I want to add a split the field and add a decimal point and create a numerical field. This is what I would like to see:
**RawField**
200602.02
200603.23
So I need to split the field, add the decimal point, and convert to a numerical value. I tried some code but was getting an error. Please see my code below:
select top 1000 cast(SUBSTRING(cast(RawField as varchar(6)),1,6) + cast('.' as varchar(1)) + SUBSTRING(cast(RawField as varchar(2)),6,2) as int)
from Table
I get an error of:
Msg 245, Level 16, State 1, Line 11
Conversion failed when converting the varchar value '200602.' to data type int.
Is this a good approach?

you want to convert the string to numeric with 2 decimal places ?
select convert(decimal(10,2), RawField) / 100.0
I guest your RawField contains other alphanumeric after that and you only posted the first 8 characters ?
this should work. Just take the first 8 characters and convert. Simple and direct
select convert(decimal(10,2), left(RawField, 8)) / 100.0

Please try this.
select top 1000 cast(SUBSTRING(cast(RawField as varchar(6)),1,6) + cast('.' as varchar(1)) + SUBSTRING(cast(RawField as varchar(2)),6,2) as numeric(8,2))
from Table
You are trying to cast string with decimal number to int.

Use float/numeric/decimal when casting
select cast(SUBSTRING(RawField ,1,6) + cast('.' as varchar(1)) + SUBSTRING(RawField ,7,2) as numeric(16,2))

Related

How to convert from nchar to decimal in SQL?

I have 2 tables(source and destination) which are respectively NOR_LABOR and ALL_LABOR_DETAILS. In the source table(NOR_LABOR) there is a column "feet_produced" with the data type "nchar(10)". In the destination table(ALL_LABOR_DETAILS) there's a column "labor_feet_produced" with the data type "decimal(18,4)". I want to convert the "feet_produced" from nchar(10) to decimal(18,4) and paste it in the "ALL_LABOR_DETAILS" table's "labor_feet_produced" column.
I have found a code regarding a simillar issue but did not do the exact as I need to do, following is that code snippet :
Select feet_produced AS feet_produced_s, CASE WHEN Isnumeric(feet_produced) = 1
THEN CONVERT(DECIMAL(18,2),feet_produced)
ELSE 0 END AS feet_produced
INTO [MES_DEV].[dbo].[ALL_LABOR_DETAILS]
from [dbo].[NOR_LABOR]
Thank you!
There are values that will test true for IS_NUMERIC, but will fail to convert to decimal.
Instead, use TRY_CONVERT which will return either the successfully-converted-to-decimal value, or a NULL when it fails. (You can then COALESCE to zero to get your desired result).
Here is a short example set of values, using TRY_CONVERT:
SELECT
TryConvert = COALESCE(TRY_CONVERT(decimal(18,4),TestValues),0)
FROM (
VALUES('10.6'),
('ten'),
('7d2'),
('10000000000'),
('10.00000001')
) AS x(TestValues);
The same set of values using your example code will throw an error:
SELECT
IsNumericCase = CASE
WHEN Isnumeric(TestValues) = 1
THEN CONVERT(DECIMAL(18,2),TestValues)
ELSE 0
END
FROM (
VALUES('10.6'),
('ten'),
('7d2'),
('10000000000'),
('10.00000001')
) AS x(TestValues);
This error is returned because 7d2 is numeric, but cannot be converted to decimal.
Msg 8114, Level 16, State 5, Line 14
Error converting data type varchar to numeric.
Im not sure what the issue is with the code that dose not work for you.
But here is how I would do it with a small change in the statement that you just post it.
insert into[MES_DEV].[dbo].[ALL_LABOR_DETAILS](labor_feet_produced)
select CONVERT(DECIMAL(18, 4), feet_produced) AS feet_produced_s from[dbo].[NOR_LABOR]

Concatenate and add a character to integer columns in SQL

I have a 10 Character length values in a column in SQL Server. I need to split that column at fixed length and remove the leading zeros and add a - after each of the values.
I am able to split the values by using Substring and converting them to int. It is working well.
However, when I try to concatenate it is failing. Appreciate if you can help.
SELECT TOP 1 R.COL1, CAST(SUBSTRING(R.COL1,1,1) AS int) AS F1,CAST(SUBSTRING(R.COL1,2,5) AS int) AS F2,CAST(SUBSTRING(R.COL1,7,4) AS int) AS F3 CAST(SUBSTRING(R.COL1,1,1) AS int) +'-' +CAST(SUBSTRING(R.COL1,2,5) AS int) +'-' + CAST(SUBSTRING(R.COL1,7,4) AS int) AS finalString FROM MYTABLE R
If the value for COL1 IS 1012950001 the finalString I am expecting is 1-1295-1
however the result I am getting from the above query is 1297 as it is adding all the values.
Appreciate if you can help.
You can't use the + operator with a numerical data type and a varchar that cannot implicitly be converted to that data type. Something like 1 + 'a' isn't going to work, as 'a' isn't an int, and can't be implicitly converted to one.
If you are mixing data types, then use CONCAT, which implicitly converts each part into a (n)varchar:
CONCAT({Numerical Expression},'a',{Other varchar Expression})
You can use concat method to concatenate the substring value
select
concat(CAST(SUBSTRING('1012950001',1,1) AS int), '-',
CAST(SUBSTRING('1012950001',2,5) AS int), '-',
CAST(SUBSTRING('1012950001',7,4) AS int)) AS finalString
This will give you the expected result '1-1295-1'

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)

Sum of data in varchar column

i have to sum element in a column(SCENARIO1) that is varchar and contain data like (1,920, 270.00, 0, NULL) but when i try to convert data into int or decimal i get this error :
"he command is wrong when converting value "4582014,00" to int type"
here is my request :
select sum( convert( int, SCENARIO1) )
from Mnt_Scenario_Exercice where code_pere='00000000'
any help please
try this
select sum(cast(replace(SCENARIO1, ',', '.') as decimal(29, 10)))
from Mnt_Scenario_Exercice
where code_pere = '00000000';
If you couldn't convert your '4582014,00' into decimal, there's a chance you have different decimal separator on your server. You could look what it is or just try '.'
4582014,00 should be a decimal
try this (I assume that youre query is working) and changed convert(int into decimal)
select sum(convert(decimal(20,2),replace(SCENARIO1, ',', '.'))) from Mnt_Scenario_Exercice where code_pere='00000000'
The problem is due to the fact that the sum function isn't decoding SCENARIO1 as containing a CSV list of numbers. The way the sum function is usually used is to sum a lot of numbers drawn from multiple rows, where each row provides one number.
Try doing it in two steps. In step 1 convert the table into first normal form perhaps by UNPIVOTING. The 1NF table will have one number per row, and will contain more rows than the initial table.
The second step is to compute the sum. If you want more than one sum in the result, use GROUP BY to create groups, and then select a sum(somecolumn). This will yield one sum for each group.
Try this, I haven't got a way to test yet, but I will test and replace if incorrect.
SELECT sum(CAST (replace(SCENARIO1, ',', '') AS INT))
FROM Mnt_Scenario_Exercice
WHERE code_pere = '00000000';
EDIT: You can use a numeric for the cast if you need 4582014,00 to be 4582014.00
SELECT sum(CAST (replace(SCENARIO1, ',', '.') AS NUMERIC(10,2)))
FROM Mnt_Scenario_Exercice
WHERE code_pere = '00000000';

Truncate (not round) decimal places in SQL Server

I'm trying to determine the best way to truncate or drop extra decimal places in SQL without rounding. For example:
declare #value decimal(18,2)
set #value = 123.456
This will automatically round #value to be 123.46, which is good in most cases. However, for this project, I don't need that. Is there a simple way to truncate the decimals I don't need? I know I can use the left() function and convert back to a decimal. Are there any other ways?
ROUND ( 123.456 , 2 , 1 )
When the third parameter != 0 it truncates rather than rounds.
Syntax
ROUND ( numeric_expression , length [ ,function ] )
Arguments
numeric_expression
Is an expression of the exact numeric or approximate numeric data
type category, except for the bit data type.
length
Is the precision to which numeric_expression is to be rounded. length must be an expression of type tinyint, smallint, or int. When length is a positive number, numeric_expression is rounded to the number of decimal positions specified by length. When length is a negative number, numeric_expression is rounded on the left side of the decimal point, as specified by length.
function
Is the type of operation to perform. function must be tinyint, smallint, or int. When function is omitted or has a value of 0 (default), numeric_expression is rounded. When a value other than 0 is specified, numeric_expression is truncated.
select round(123.456, 2, 1)
SELECT Cast(Round(123.456,2,1) as decimal(18,2))
Here's the way I was able to truncate and not round:
select 100.0019-(100.0019%.001)
returns 100.0010
And your example:
select 123.456-(123.456%.001)
returns 123.450
Now if you want to get rid of the ending zero, simply cast it:
select cast((123.456-(123.456%.001)) as decimal (18,2))
returns 123.45
Actually whatever the third parameter is, 0 or 1 or 2, it will not round your value.
CAST(ROUND(10.0055,2,0) AS NUMERIC(10,2))
Do you want the decimal or not?
If not, use
select ceiling(#value),floor(#value)
If you do it with 0 then do a round:
select round(#value,2)
Another truncate with no rounding solution and example.
Convert 71.950005666 to a single decimal place number (71.9)
1) 71.950005666 * 10.0 = 719.50005666
2) Floor(719.50005666) = 719.0
3) 719.0 / 10.0 = 71.9
select Floor(71.950005666 * 10.0) / 10.0
Round has an optional parameter
Select round(123.456, 2, 1) will = 123.45
Select round(123.456, 2, 0) will = 123.46
ROUND(number, decimals, operation)
number => Required. The number to be rounded
decimals => Required. The number of decimal places to round number to
operation => Optional. If 0, it rounds the result to the number of decimal. If another value than 0, it truncates the result to the number of decimals. Default value is 0
SELECT ROUND(235.415, 2, 1)
will give you 235.410
SELECT ROUND(235.415, 0, 1)
will give you 235.000
But now trimming0 you can use cast
SELECT CAST(ROUND(235.415, 0, 1) AS INT)
will give you 235
This will remove the decimal part of any number
SELECT ROUND(#val,0,1)
SELECT CAST(Value as Decimal(10,2)) FROM TABLE_NAME;
Would give you 2 values after the decimal point. (MS SQL SERVER)
Another way is ODBC TRUNCATE function:
DECLARE #value DECIMAL(18,3) =123.456;
SELECT #value AS val, {fn TRUNCATE(#value, 2)} AS result
LiveDemo
Output:
╔═════════╦═════════╗
║ val ║ result ║
╠═════════╬═════════╣
║ 123,456 ║ 123,450 ║
╚═════════╩═════════╝
Remark:
I recommend using built-in ROUND function with 3rd parameter set to 1.
I know this is pretty late but I don't see it as an answer and have been using this trick for years.
Simply subtract .005 from your value and use Round(#num,2).
Your example:
declare #num decimal(9,5) = 123.456
select round(#num-.005,2)
returns 123.45
It will automatically adjust the rounding to the correct value you are looking for.
By the way, are you recreating the program from the movie Office Space?
Try like this:
SELECT cast(round(123.456,2,1) as decimal(18,2))
If you desire to take some number like 89.0904987 and turn it into 89.09 by simply omitting the undesired decimal places, simply use the following:
select cast(yourColumnName as decimal(18,2))
The following screenshot is from W3Schools SQL Data Types section, which describes what decimal(18,2) is doing:
Therefore,
select cast(89.0904987 as decimal(18,2))
gives you: 89.09
Please try to use this code for converting 3 decimal values after a point into 2 decimal places:
declare #val decimal (8, 2)
select #val = 123.456
select #val = #val
select #val
The output is 123.46
I think you want only the decimal value,
in this case you can use the following:
declare #val decimal (8, 3)
SET #val = 123.456
SELECT #val - ROUND(#val,0,1)
I know this question is really old but nobody used sub-strings to round. This as advantage the ability to round really long numbers (limit of your string in SQL server which is usually 8000 characters):
SUBSTRING('123.456', 1, CHARINDEX('.', '123.456') + 2)
I think we can go much easier with simpler example solution found in Hackerrank:
Problem statement: Query the greatest value of the Northern Latitudes
(LAT_N) from STATION that is less than 137.2345. Truncate your answer
to 4 decimal places.
SELECT TRUNCATE(MAX(LAT_N),4)
FROM STATION
WHERE LAT_N < 137.23453;
Solution Above gives you idea how to simply make value limited to 4 decimal points. If you want to lower or upper the numbers after decimal, just change 4 to whatever you want.
Mod(x,1) is the easiest way I think.
select convert(int,#value)