How can I count number of digits after decimal point - sql-server

How can I count the number of digits after decimal point in SQL Server 2008?
Eg: 1.99999999495049E-05
I need to know how many digits there are after the decimal point.

If you want to count the number of digits after decimal then the below query works fine.
SELECT LEN(SUBSTRING(cast(COLUMNNAME as varchar), CHARINDEX('.',COLUMNNAME ) + 1, 1000)) AS DIGITSAFTERDECIMALPOINTS
FROM TABLENAME
Hope this helps!

Wow, that's superbly tricky. This sort of logic should get you there:
DECLARE #Value float(53) = 1.99999999495049E-5;
DECLARE #StringValue varchar(40) = CONVERT(varchar(40), #Value, 2);
DECLARE #ELocation int = CHARINDEX('e', #StringValue);
DECLARE #ExponentDigits int = 0 - CAST(SUBSTRING(#StringValue, #Elocation + 1, 40) AS int);
DECLARE #MantissaString varchar(40) = REPLACE(SUBSTRING(#StringValue, 1, #ELocation - 1), '.', '');
DECLARE #NumberOfMantissaDigits int = LEN(CAST(CAST(REVERSE(#MantissaString) AS bigint) AS varchar(20)));
SELECT #ExponentDigits + #NumberOfMantissaDigits - 1 AS NumberOfDecimalPlaces;
I've left them all as separate statements so you can work out what's going on. I could put it all in a single line expression but I'd shudder to try and understand it later.

If you would like to count the number of digits after a decimal point in Teradata
SELECT LENGTH(SUBSTRING(COLUMN_NAME FROM POSITION('.' IN COLUMN_NAME) + 1 FOR 1000))
FROM TABLE

Related

Convert number from 002541500(Last 4 digits are decimal places) to 254.1500 using sql server

Convert number from 002541500(Last 4 digits are decimal places) to 254.1500 in sql server
This is simple maths:
CONVERT(int,Yourcolumn) / 10000.00
If you have to have 4 decimal places, use CONVERT:
CONVERT(decimal(10,4), CONVERT(int,YourColumn) / 10000.00)
declare #i varchar(50) = '00251500'
--Option 1:
select convert(decimal(9,4), CONVERT(int, #i) / 10000.00)
By multiplying the varchar with 1, the basetype gets converted to numeric. By multiplying this result with .0001 the scale changes from 0 to 4.
SELECT 1 * '902541501' * .0001
Result
90254.1501
SQL_VARIANT_PROPERTY:
SELECT
SQL_VARIANT_PROPERTY(1 * '902541501' * .0001, 'BaseType') BaseType,
SQL_VARIANT_PROPERTY(1 * '902541501' * .0001, 'Scale') Scale
Result
BaseType Scale
numeric 4
I found the way to fix the issue
declare #imp_ori varchar(50) = '00251500'
select
cast(left(#imp_ori,4) + '.' + right(#imp_ori,4) as numeric(10,4)) as StringBuildCast
result: 25.1500

TSQL remap big number to smaller, but keep Identity

I'm trying to load a huge number into Field1 INT which can hold only max=2,147,483,647, according to it I can't change DDL, so tried to find adhoc solution to cut out single digit from the middle of this number and then add check for uniqueness.
This numbers are in the format like: 29000001234, so I mean to keep this format with zeros in the middle to easy recognizing. I don't want to introduce any new columns/tables into this task, as limited in freedom there, this is 3rd party schema.
Can anybody suggest better solution, how to remap/keep all numbers under that limit; this is my draft:
DECLARE #fl FLOAT = 29000001234
DECLARE #I INT
SELECT #i = (SUBSTRING(CAST(CAST(#fl AS BIGINT) AS VARCHAR(18)),1,4) +
SUBSTRING(CAST(CAST(#fl AS BIGINT) AS VARCHAR(18)),7,LEN(CAST(CAST(#fl AS BIGINT) AS VARCHAR(18)))) )
select #i;
But if you really want to remove the middle digits, here's another approach:
DECLARE #fl FLOAT = 29000001234
DECLARE #I INT
DECLARE #StringFloat as varchar(80)
SET #StringFloat = CONVERT(varchar(80), CAST(#fl AS bigint))
SET #I = CAST( CONCAT(LEFT( #StringFloat, 4 ), RIGHT( #StringFloat, 5 )) as int )
SELECT #i;
I think arithmetic operations should be less expensive than string operations, so you should use them instead:
DECLARE #fl FLOAT = 29000001234
DECLARE #flBig BIGINT = #fl
DECLARE #i INT
SET #i = (#flBig / 1000000000) * 10000000 + (#flBig % 100000000)
select #i; --> 290001234
Provided example assumes the first part of the number will have a maximum of two digits (i.e. 29 in your case) and that you want to allow larger number in the left part (up to 999999).
NOTE: parentheses are redundant, as division and multiplication have the same priority and modulo operator has higher precedence over addition. I have used them just to highlight the parts of the computation.
You can't do that without any arithmetic overflow, or with out losing your original data.
If you have a limitation in columns of your destination table or query, use multiple rows:
declare #c bigint = 29000001234;
declare #s bigint = 1000000000; -- Separator value
;with cte(partNo, partValue) as (
select 1, #c % #s
union all
select partNo + 1, (#c / power(#s, partNo)) % #s
from cte
where (#c / power(#s, partNo)) > 0
)
select partValue
from cte;
Seems like a strange situation, not sure why you need to go to all the trouble of converting a big number to a string and then randomly remove a digit. Some more information about why or what the real goal is would be helpful.
That said, maybe it would be easier to just subtract a constant amount from these values? e.g.:
DECLARE #fl FLOAT = 29000001234
DECLARE #I INT
DECLARE #OFFSET BIGINT = 29000000000
SET #I = CAST(#fl AS BIGINT)-#OFFSET
SELECT #I
Which gives you an INT of 1234 as the result using your example.
The following creation drops increasingly wide blocks of digits from the original third party value and returns the results that fit in an INT. The results could be outer joined with the existing data to find a suitable new value.
declare #ThirdPartyValue as BigInt = 29000001234;
declare #MaxInt as BigInt = 2147483647;
declare #TPV as VarChar(19) = Cast( #ThirdPartyValue as VarChar(19) );
declare #TPVLen as Int = Len( #TPV );
with
-- 0 through 9.
Digits as (
select Digit from ( values (0), (1), (2), (3), (4), (5), (6), (7), (8), (9) ) as Digits( Digit ) ),
-- 0 through #TPVLen .
Positions as (
select Ten_1.Digit * 10 + Ten_0.Digit as Number
from Digits as Ten_0 cross join Digits as Ten_1
where Ten_1.Digit * 10 + Ten_0.Digit <= #TPVLen ),
-- 1 through #TPVLen - 1 .
Widths as (
select Number
from Positions
where 0 < Number and Number < #TPVLen ),
-- Try dropping Width digits at Position from #TPV .
AlteredTPVs as (
select P.Number as Position, W.Number as Width,
Stuff( #TPV, P.Number, W.Number, '' ) as AlteredTPV
from Positions as P cross join Widths as W
where P.Number + W.Number <= #TPVLen )
-- See which results fit in an Int .
select Position, Width, AlteredTPV, Cast( AlteredTPV as BigInt ) as AlteredTPVBigInt
from AlteredTPVs
where Cast( AlteredTPV as BigInt ) <= #MaxInt -- Comment out this line to see all results.
order by Width, Position
It could be more clever about returning only distinct new values.
This general idea could be used to hunt down blocks of zeroes or other suitable patterns to arrive at a set of values to be tested against the existing data.

Remove the 7th digit of a bigint for every row in a Sql Server table

I am maintaining SQL Server database and some c# code which uploads data to it from a third party. The database has a table 'LessonRoom' which contains a row for each lesson which occurs in a particluar room, it has a field 'SourceKey' which is a bigint and is formed by concatenating a room id and a lesson id, the c# which returns this key is as follows:
SourceKey = long.Parse(RoomId.ToString().PadRight(7, '0') + LessonId.ToString());
This code started falling over because the lessonId's grew too large and the resulting int is too large to fit in a bigint (c# long). The RoomIds are only ever 5 digits long so an easy fix is to PadRight(6, '0').
Now I have a solution but I need to update the existing data. I don't know how to remove a zero from the 7th digit of a SQL Server bigint in every row of 500,000 rows. Do I have to write a query to convert the value to a string, remove the zero, parse and put it back or can anyone think of a more succinct way to do it?
Essentially I need to turn this number:
6,159,800,830,114,069,893
Into this one:
615,980,830,114,069,893
Sine you know it is always the 7th character you want to remove you can do this quite easily.
declare #SourceKey bigint = 6159800830114069893
select cast(stuff(cast(#SourceKey as varchar(25)), 7, 1, '') as bigint)
you could resolve them with the modulo-Operator :)
here a simple T SQL example
DECLARE #input AS BIGINT
DECLARE #expect AS BIGINT
DECLARE #rest AS BIGINT
DECLARE #result AS BIGINT
DECLARE #resultShort AS BIGINT
SET #input = 6159800830114069893
SET #expect= 615980830114069893
SET #rest = #input % 1000000000000
SET #result = ( ( #input - #rest ) / 10 ) + #rest
SET #resultShort = ( ( #input - #input % 1000000000000 ) / 10 ) + #input %
1000000000000
SELECT #rest, #result,
CASE
WHEN #result = #expect THEN 'true'
ELSE 'false'
END AS test,
#resultShort,
CASE
WHEN #resultShort = #expect THEN 'true'
ELSE 'false'
END AS test2

How to add or concatenate money type and string on query mssql

I have a situation like this
I got a column with 'money' type, 2 decimal . Example data:(65.00)
I need to add 12 zero / 000000000000 to it so that the output would be like this:
(65.00 convert to 6500) + (000000000000) = 000000006500
Output: 000000006500
How can I achieve this?. Thank you for your help and suggestion
You can do this with a couple of casts, multiplying by 100, and using REPLICATE('0') to pad with the requisite number of zeroes).
I'm assuming you DO want up to 2 x trailing decimals, but no more.
DECLARE #value MONEY;
SET #value = 65.123;
DECLARE #intValue BIGINT;
SET #intValue = CAST(#value * 100.0 AS BIGINT);
SELECT REPLICATE('0',12-LEN(#intValue)) + CAST(#intValue AS NVARCHAR(20));
Returns 000000006512
If you need to do this on a set, a CTE can be used for the intermediate step, e.g.
WITH cte AS
(
SELECT CAST(MoneyField * 100.0 AS BIGINT) AS intValue
FROM SomeTable
)
SELECT
REPLICATE('0',12-LEN(cte.intValue)) + CAST(cte.intValue AS NVARCHAR(20))
FROM cte;
Fiddle here
It is Possible .But output Column should be in the type of varchar(15) .If you want to do further operation of your output you have to convert that into int or whatever
SELECT CONCAT(REPEAT('0',12-LENGTH(65.00)),(65.00*100));

Convert Hexadecimal to INT and vice versa

I will be creating a sequential Serial Number made from Hexadecimal values
With this Format:
XX-XX-XX-YYYY
Which XX-XX-XX is default value
And YYYY is the incrementing hexa decimal value
Now to create the serial number based on hex value I need Add 6 to the last generated hex value
MIN: 2D41 + 6 = 2D47
2D47 + 6 ... and so on
MAX: 4100 generation of serial will stop when I meet the MAX value.
I already created it in c# but I need to do it on SQL
int num1 = int.Parse("2D41", NumberStyles.HexNumber); //Convert hex to int
int result = num1 + 6; //Add + 6 for increment
string myHex = result.ToString("X"); //Convert result to hex
MessageBox.Show(myHex); // result 2D47
How can this be done in T-SQL?
DECLARE #x VARBINARY(8) = 0x00002D41;
SELECT CONVERT(VARBINARY(8), CONVERT(INT, #x) + 6);
In order to handle the output as a string:
DECLARE #x VARBINARY(8) = 0x00002D41;
SELECT CONVERT(CHAR(10), CONVERT(VARBINARY(8), CONVERT(INT, #x) + 6), 1);
Hope this helps you
declare #seed varchar(max) = '2D41';
declare #limit varchar(max) = '4100';
select convert(int, convert(varbinary(max), '0x'+#seed,1)),
convert(int, convert(varbinary(max), '0x'+#limit,1));
;with seedlimit(seed, limit) as (
select convert(int, convert(varbinary(max), '0x'+#seed,1)),
convert(int, convert(varbinary(max), '0x'+#limit,1))
)
select SerialNumber = 'XX-XX-XX-' + right(convert(varchar(10),cast(s.seed + 6 * v.number as varbinary(max)),1),4)
from seedlimit s
join master.dbo.spt_values v on type='p'
where s.seed + 6 * v.number <= s.limit;
The basic ingredients are in there for you to create a view/procedure/function out of the answer,
Output:
SerialNumber
-------------
XX-XX-XX-2D41
XX-XX-XX-2D47
...
XX-XX-XX-40F7
XX-XX-XX-40FD
If you already have it in C#, leave it there and simply convert your code to a SQL CLR function.
For a simple example see:
http://blog.sqlauthority.com/2008/10/19/sql-server-introduction-to-clr-simple-example-of-clr-stored-procedure/

Resources