如何从浮点数中获得前n个数字

时间:2015-02-11 12:03:33

标签: sql sql-server

我的表A有两列id(int)f_value(float)。现在我想选择f_value从'123'开始的所有行。所以对于下表:

id | f_value
------------
1  | 12
2  | 123
3  | 1234

我想获得第二和第三行。我尝试使用LEFT和演员,但这是一场灾难。对于以下查询:

select f_value, str(f_value) as_string, LEFT(str(f_value), 2) left_2,
       LEFT(floor(f_value), 5) flor_5, LEFT('abcdef', 5) test
   from A

我得到了:

f_value  | as_string | left_2 | flor_5 | test
------------------------------------------------
40456510 | 40456510  |        | 4.045  |  abcde
40454010 | 40454010  |        | 4.045  |  abcde
404020   | 404020    |        | 40402  |  abcde
40452080 | 40452080  |        | 4.045  |  abcde
101020   | 101020    |        | 10102  |  abcde
404020   | 404020    |        | 40402  |  abcde

问题是为什么左边的“测试”可以正常工作,但是对于其他返回这样奇怪的结果呢?

修改

我做了另一个测试我现在更加困惑。查询:

Declare @f as float
set @f = 40456510.

select LEFT(cast(@f as float), LEN(4045.)), LEFT(404565., LEN(4045.))

我得到了:

     |
------------ 
4.04 | 4045

是否存在导致此问题的默认演员表? Fiddle SQL

6 个答案:

答案 0 :(得分:0)

CREATE TABLE #TestTable(ID INT, f_value FLOAT)
INSERT INTO #TestTable
VALUES  (1,22),
        (2,123),
        (3,1234)

SELECT *
FROM #TestTable
WHERE LEFT(f_value,3)='123'

DROP TABLE #TestTable

我希望这会有所帮助。

答案 1 :(得分:0)

好像你的查询有点不对劲。 LEFT部分应该放在WHERE - 条款中,而不是SELECT - 部分。

另外,只需使用LIKE即可,您应该没问题:

SELECT f_value, str(f_value) as_string, LEFT(str(f_value), 2) left_2,
       LEFT(floor(f_value), 5) flor_5
WHERE f_value LIKE '123%'

答案 2 :(得分:0)

使用FLOATDECIMAL值转换为VARCHAR然后转换为CAST并使用LIKE选择以4045开头的值。< / p>

<强>查询

SELECT * FROM tbl
WHERE CAST(CAST(f_value AS DECIMAL(20,12)) AS VARCHAR(MAX)) LIKE '4045%';

Fiddle demo for reference

答案 3 :(得分:0)

替换摆脱浮动中的句点,乘以1前面的任何0将被删除。

SELECT f_value
FROM your_table
WHERE replace(f_value, '.', '') * 1 like '123%'

答案 4 :(得分:0)

我找到了解决方案。问题是SQL Server使用浮点数的指数表示。要解决它,您需要先将float转换为BigInt,然后在其上使用Left。

示例:

Select * from A where Left(Cast(float_value as BigInt), 4) = xxxx 

答案 5 :(得分:0)

/*
returns significant digits from @f (a float) as an integer
negative sign is stripped off
*/
declare @num_digits int = 3; /* needs to be positive; accuracy diminishes with larger values */
with samples(num, f) as (
    select 1, cast(123.45 as float) union
    select 2, 123456700 union
    select 3, -1.234567 union
    select 4, 0.0000001234
)
select num, f,
    case when f = 0 or @num_digits < 1 then 0 else
        floor(
            case sign(log10(abs(f)))
                when -1 then abs(f) * power(10e0,  -floor(log10(abs(f))) + @num_digits - 1)
                when  1 then abs(f) / power(10e0, ceiling(log10(abs(f))) - @num_digits)
            end
        )
    end as significant_digits
from samples
order by num;

sqlfiddle