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
Related
I am working on the usage of the Cast function in SQL Server. If I use explicit value as written in the code. The output is 38 which is the correct value. But I would need to use field names instead of direct values(There is only value of Base, escalator here ; Base =1.15 and escalator=0.05. But when I use field names, the output is 37. The data type of Base and escalator fields is float. I also tried using round function inside cast, did not solve the issue. Could someone out here help me with this. My query below:
Select CAST((3.05-1.15)/0.05 AS INT) -- returns 38
Select ((3.05-1.15)/0.05) --returns 38
Select cast((3.05-base)/Escalator) as int) from table1 -- I am using field names here. Returns 37
What is likely happening here is that the base and Escalator columns are some kind of non exact floating point type. As a result, the following computation results a value which is slightly less than 38:
(3.05-base) / Escalator = 37.999995 (for example)
Then, when casting to integer, the entire decimal component is being truncated, leaving behind just 37.
One possible workaround to prevent this from happening would be to use NUMERIC or some other exact type for the base and Escalator columns.
You can use Decimal to get rid of the issue
DECLARE #Escalator DECIMAL(7, 5) = 0.05
Select ((3.05-1.15)/0.05) --returns 38
Select CAST(((3.05-1.15)/#Escalator) AS INT) -- returns 38
Demo on db<>fiddle
you can use ceiling or floor inbuilt function based on your requirement
DECLARE #Escalator float = 0.05
DECLARE #Base float = 1.66
Select ((3.05-1.66)/0.05) --returns 27.8
Select ceiling (((3.05-#Base)/#Escalator)) -- returns 28
Select floor (((3.05-#Base)/#Escalator)) -- returns 27
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
I'm using SQL Server's POWER function in a user function and when the base is a negative number and the exponent is a fraction I'm getting an error,
[MICROSOFT][ODBC SQL SERVER DRIVER][SQL SERVER]AN INVALID FLOATING POINT OPERATION OCCURRED.
A negative base can be raised to a power in the real world, so is this an SQL bug? If so is there a work around?
Example:
SELECT POWER(-.2, 9.7)
Further refinement of the issue
-- These work
SELECT
POWER(-.2, 9)
, POWER(.2, 9.7);
-- This does not
SELECT
POWER(-.2, 9.7);
-- POWER on BOL http://msdn.microsoft.com/en-us/library/ms174276.aspx
-- Returns the same type as submitted in float_expression
-- Perhaps something is awry with typing
DECLARE
#f decimal(35,30) = -.2
, #fout decimal(35,30);
-- This still fails with "An invalid floating point operation occurred"
SELECT
#fout = POWER(#f, 9.7);
The result of POWER(-.2, 9.7) would be, at best, an imaginary number, and cannot be represented as a single floating-point number.
You could convert the floating-point exponent to a fraction and rewrite it as POWER(-.2,97/10) which is equivalent to POWER(POWER(-.2,97) , 1/10). Since the Nth roots of a negative number are real if N is odd but imaginary if N is even, POWER(-.2,1/10) would be a complex number.
Note that POWER(-.2, 0.8) could be evaluated as a real number since it would just be equivalent to POWER(-.2,4/5) and the 5th root of -.2 is real, but my guess is that SQL doesn't even bother trying to determine if the exponent could be represented as a fraction with an odd denominator and throws an error.
It appears that SQL Server just does not let you do fractional exponents for negative base numbers.
There's some discussion here: Raising numbers to fractional powers in SQL
I did some testing, just to see what works and what doesn't, using this query:
create table #test(b float, val float, success bit default (0));
declare #a float = -1, #b decimal(3,2) = 0.01
WHILE #b < 2
BEGIN
INSERT INTO #test(b) VALUES(#b);
BEGIN TRY
UPDATE #test SET val = POWER(#a, #b), success = 1 WHERE b = #b
END TRY
BEGIN CATCH
PRINT ##error
END CATCH
SELECT #b += .01;
END
select * from #test
If you notice, even steps that should work without giving a complex number error out. The only result that works correctly is 1.
I am using LIKE to return matching numeric results against a float field. It seems that once there are more than 4 digits to the left of the decimal, values that match my search item on the right side of the decimal are not returned. Here's an example illustrating the situation:
CREATE TABLE number_like_test (
num [FLOAT] NULL
)
INSERT INTO number_like_test (num) VALUES (1234.56)
INSERT INTO number_like_test (num) VALUES (3457.68)
INSERT INTO number_like_test (num) VALUES (13457.68)
INSERT INTO number_like_test (num) VALUES (1234.76)
INSERT INTO number_like_test (num) VALUES (23456.78)
SELECT num FROM number_like_test
WHERE num LIKE '%68%'
That query does not return the record with the value of 12357.68, but it does return the record with the value of 3457.68. Also running the query with 78 instead of 68 does not return the 23456.78 record, but using 76 returns the 1234.76 record.
So to get to the question: why having a larger number causes these results to change? How can I change my query to get the expected results?
The like operator requires a string as a left-hand value. According to the documentation, a conversion from float to varchar can use several styles:
Value Output
0 (default) A maximum of 6 digits. Use in scientific notation, when appropriate.
1 Always 8 digits. Always use in scientific notation.
2 Always 16 digits. Always use in scientific notation.
The default style will work fine for the six digits in 3457.68, but not for the seven digits in 13457.68. To use 16 digits instead of 6, you could use convert and specify style 2. Style 2 represents a number like 3.457680000000000e+003. But that wouldn't work for the first two digits, and you get an unexpected +003 exponent for free.
The best approach is probably a conversion from float to decimal. That conversion allows you to specify the scale and precision. Using scale 20 and precision 10, the float is represented as 3457.6800000000:
where convert(decimal(20,10), num) like '%68%'
When you are comparing number with LIKE it is implicitly converted to string and then matched
The problem here is that float number is not precise and when it is converted you can get
13457.679999999999999 instead of 13457.68
So to avid this explicitly format number in appropriate format(not sure how to do this in sql server, but it will be something like)
SELECT num FROM number_like_test
WHERE Format("0.##",num) LIKE '%68%'
The conversion to string is rounding your values. Both CONVERT and CAST have the same behavior.
SELECT cast(num as nvarchar(50)) as s
FROM number_like_test
Or
SELECT convert(nvarchar(50), num) as s
FROM number_like_test
provide the results:
1234.56
3457.68
13457.7
1234.76
23456.8
You'll have to use the STR function and correct format parameters to try to get your results. For example,
SELECT STR(num, 10, 2) as s
FROM number_like_test
gives:
1234.56
3457.68
13457.68
1234.76
23456.78
Pretty well solved already, but you only need to CAST once, not twice like the other answer suggests, LIKE takes care of the string conversion:
SELECT *
FROM number_like_test
WHERE CAST(num AS DECIMAL(12,6)) LIKE '%68%'
And here's a SQL Fiddle showing the rounding behavior: SQL Fiddle
It's probably because a FLOAT data type represents a floating point number which is an approximation of the number and should not be relied on for exact comparisons.
If you need to do a search that includes the float value you would need to either store it in a decimal data type (which will hold the exact number) or convert it to a varchar using something like the STR() function
I am just stuck in this situation. Is there any way in SQL
to get rid off from all numbers except two numbers after decimal point?
for example, lets say 125.36987 so as the output i want only 125.36.
Ive tried to multiply it to 100 then use cast it to int and divide by 100.0
but still getting not what i want.
YES,ROUND CAN SOLVE THAT.
SELECT ROUND(125.36987,2) FROM DUAL; YOU CAN GET 125.37
Or if YOU DON'T NEED round-off , you can use 'trunc'
like this TRUNC(125.36987,2) 125.36
use ROUND()
select round(125.36987, 2, 1)
SQLFiddle Demo
ROUND
Here's the detail. the syntax,
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.