Numeric precision as variable - sql

Declare #Precision INTEGER
Set #precision = 3
-> I have a select statement here which selects the integer value
and if their is a way that I can use this #precision in numeric data type for example something like this
numeric(20,#precision)

You want to use the str() function (documented here).
It allows you to convert numerics to strings, while controlling the precision.
For instance:
select str(3.14158165, 5, 3)
Returns '3.142'.

Related

Cast a hexadecimal string to an array of bigint in hive

I have a column that contains a length 16 hexademical string. I would like to convert it to a bigint. Is there any way to accomplish that? The usual approach returns null since the input string could represent a number > 2^63-1.
select
cast(conv(hash_col, 16, 10) as bigint) as p0,
conv(hash_col, 16, 10) as c0
from mytable limit 10
I have also tried using unhex(..),
cast(unhex(hash_col) as bigint) as p0 from mytable limit 10
but got the following error
No matching method for class org.apache.hadoop.hive.ql.udf.UDFToLong
with (binary). Possible choices: FUNC(bigint) FUNC(boolean)
FUNC(decimal(38,18)) FUNC(double) FUNC(float) FUNC(int) FUNC(smallint) FUNC(string) FUNC(timestamp) FUNC(tinyint) FUNC(void)
If I don't do the cast(.. as bigint) part, I get some undisplayable binary value for p0. It seems unhex is not exactly the inverse of hex in hive.
Your values are out of range for BigInt
Ref : https://cwiki.apache.org/confluence/display/Hive/LanguageManual+Types
Max range for BigInt is 9,223,372,036,854,775,807
Use decimal(20,0) instead.
select cast(conv('85A58F8B014692CA',16,10) as decimal(20,0))

Roundoff error in sql

DECLARE #TAX VARCHAR(30)=120.45
DECLARE #TaxRoundOf VARCHAR(30)
SET #TaxRoundOf=ROUND(#TAX,1)
SELECT #TaxRoundOf
This Gives Result (#TaxRoundOf=120.5)
DECLARE #TAX VARCHAR(30)=146.45
DECLARE #TaxRoundOf VARCHAR(30)
SET #TaxRoundOf=ROUND(#TAX,1)
SELECT #TaxRoundOf
This Gives Result (#TaxRoundOf=146.4)
But I need to return 146.50 . why this mismatch between two results?
any one can help plz?
Since you are using VARCHAR to store your numbers, SQL Server is having to do implicit conversion to float behind the scenes, which is having knock on effects on your calculations. You can reproduce this using the below query:
SELECT ROUND(CONVERT(FLOAT, 120.45),1), -- 120.5
ROUND(CONVERT(FLOAT, 146.45),1), -- 146.4
ROUND(CONVERT(DECIMAL(10, 2), 120.45),1), -- 120.50
ROUND(CONVERT(DECIMAL(10, 2), 146.45),1) -- 146.50
Since floating point numbers are not exact, 146.45 cannot be exactly represented as a float, and ends up being stored as a very slightly smaller number, so when this is passed to the round function, it is rounded down, instead of up.
The solution, as demonstrated by the 3rd and 4th columns in the above query, is to use a more precise data type.
You can use this:
SET #TaxRoundOf=ROUND(10 * CAST(#TAX AS FLOAT)) / 10
instead of:
SET #TaxRoundOf=ROUND(#TAX,1)
DEMO
PS as #GarethD already mentioned I wouldn't use #TAX as VARCHAR type.
You can also rely on numeric rounding instead of converting your string to a float, which can lose information.
Cast a string to numeric and then round:
select round(cast('146.45' as numeric(18,2)), 1)
-- 146.50
A decimal constant is already a decimal so there's no need to cast it:
select round(146.45, 1)
-- 146.50

SQL get decimal with only 2 places with no round

I have a query (SQL Server) that returns a decimal. I only need 2 decimals without rounding:
In the example above I would need to get: 3381.57
Any clue?
You could accomplish this via the ROUND() function using the length and precision parameters to truncate your value instead of actually rounding it :
SELECT ROUND(3381.5786, 2, 1)
The second parameter of 2 indicates that the value will be rounded to two decimal places and the third precision parameter will indicate if actual rounding or truncation is performed (non-zero values will truncate instead of round).
Example
You can see an interactive example of this in action here.
Another possibility is to use TRUNCATE:
SELECT 3381.5786, {fn TRUNCATE(3381.5786,2)};
LiveDemo
If you want to control the representation, you need to output the value as a string. One method is to convert to a decimal and then to a string:
select cast(cast(total as decimal(10, 2)) as varchar(255))
Another method is to convert to a string using str(). However, this often requires the removal of spaces:
select replace(str(total, 10, 2), ' ', '')

Convert Hex To unsigned long integer in SQL

I have value like this
DECLARE #hex VARCHAR(64) = '00E0'
and I need to convert this value to a double.
I have code in C language
double conver_str_to_temp(char *strTemp)
{
int iTemp;
double fTemp;
iTemp = strtoul(strTemp, 0, 16); //strTemp is the string get from the message.
if (iTemp & 0x8000) //This means this is a negative value
{
iTemp -= 0x10000;
}
fTemp = iTemp * 0.0625;
return fTemp;
}
Result for :'00E0' is 14.000000
Result for : 'FF6B' is -9.312500
But problem is I'm not good in T-SQL.
How can I convert this C code to T-SQL function for use in SQL Server ?
There's no function to convert a string containing a hexadecimal value to a number directly. But you can use intermediate conversion to varbinary, which could then be easily converted to an integer.
However, when converting to a varbinary, you will need to specify the correct format, so that the string is interpreted as a hexadecimal value (rather than a string of arbitrary digits and letters). This
CONVERT(varbinary, '00E0')
which in fact defaults to CONVERT(varbinary, '00E0', 0), will result in every character being converted individually, because that's what the 0 format specifier does. So, every '0' will be converted to 0x30 and 'E' to 0x45, which will ultimately give you 0x30304530 – most probably not the result you want.
In contrast, this
CONVERT(varbinary, '00E0', 2)
results in 0x00E0, because the 2 format specifier tells the function to interpret the string as a (non-prefixed) hexadecimal value.
Now that you've got the correct varbinary representation of the string, you can use either of the methods suggested by #armen to convert the value to an integer: like this
CONVERT(varbinary, '00E0', 2) * 1
or like this:
CONVERT(int, CONVERT(varbinary, '00E0', 2))
To explain the former method a little, it uses implicit conversion: since the other operand of multiplication, 1, is an int and int has higher precedence than varbinary, the varbinary operand is implicitly converted to int (which gives 224 in this particular case) before the multiplication can take place.
You can read more about conversion in the manual.
try this-:
DECLARE #hex VARCHAR(64) = '00E0'
SELECT CONVERT(VARBINARY, #hex) * 1
-- OR
SELECT CONVERT(INT, CONVERT(VARBINARY, #hex))
in TSQL, you need not employ a conversion function,
SQL Server will convert the HEX value into the integer intrinsically.
in your case you can do the below
declare #hex float
set #hex = 00E0
select #hex

How to reduce the float length

Using SQL Server 2000
I want to reduce the decimal length
Query
Select 23/12 as total
Output is showing as 1.99999999999
I don't want to round the value, I want to diplay like this 1.99
Tried Query
Select LEFT(23/12, LEN(23/12) - 3) as total
The above query is working only if there is decimal value like 12.444444, but if the total is single digit means like 12 or 4 or 11...., i am getting error at run time.
How to do this.
Need Query Help
There is a very simple solution. You can find it in BOL. Round takes an optional 3rd argument, which is round type. The values are round or truncate.
ROUND numeric_expression , length [ ,function ] )
...
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.
So just do
Select ROUND(cast(23 as float)/12, 2, 1) as total
That gives 1.91. Note, if you were really seeing 1.999 - something is really wrong with your computer. 23/12 = 1.916666666(ad infinitum). You need to cast one of the numbers as float since sql is assuming they're integers and doing integer division otherwise. You can of course cast them both as float, but as long as one is float the other will be converted too.
Not terribly elegant, but works for all cases:
Select CONVERT(float,LEFT(CONVERT(nvarchar, 23.0/12.0),CHARINDEX('.',CONVERT(nvarchar, 23.0/12.0)) + 2)) as total
Scalar Function
-- Description: Truncate instead of rounding a float
-- SELECT dbo.TruncateNumber(23.0/12.0,2)
-- =============================================
CREATE FUNCTION TruncateNumber
(
-- Add the parameters for the function here
#inFloat float,
#numDecimals smallint
)
RETURNS float
AS
BEGIN
IF (#numDecimals < 0)
BEGIN
SET #numDecimals = 0
END
-- Declare the return variable here
RETURN CONVERT(float,LEFT(CONVERT(nvarchar, #inFloat),CHARINDEX('.',CONVERT(nvarchar, #inFloat)) + #numDecimals))
END
GO