2015-02-11 16 views
0

У меня есть стол A с двумя колонками id(int) и f_value(float). Теперь я хотел бы выбрать все строки, где f_value начинается с '123'. Итак, для следующей таблицы:Как получить первые n чисел от поплавка

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 

Возникает вопрос: почему левый отлично работает для «теста», но и для других возвращений таких странных результатов?

EDIT:

Я сделал еще один тест, который я теперь я еще больше запутался. По запросу:

Declare @f as float 
set @f = 40456510. 

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

я получил:

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

Есть по умолчанию отбрасывать, который вызывает это? Fiddle SQL

+1

, где левый (f_value, 3) = '123' –

+0

Что, если значение равно 12.3 или.123? –

+0

@ GordonLinoff вы, вероятно, правы, поэтому ответили в соответствии с этим предположением –

ответ

0

Я нашел решение. Проблема заключалась в том, что SQL Server использует экспоненциальное представление float. Чтобы решить эту проблему, вам нужно сначала преобразовать float в BigInt, а затем использовать Left на нем.

Пример:

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

Это не будет работать во всем диапазоне значений поплавка. Не похоже, что это проблема для вашего дела, но стоит отметить, что кто-то другой пытается это сделать. – shawnt00

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 

Я надеюсь, что это поможет.

0

Похоже, что ваш запрос немного ошибочен. Часть LEFT должна идти в WHERE-Причина, а не SELECT -part.

Кроме того, просто использовать 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%' 
+0

Does'n work. Для моего примера это вернет только вторую строку. – orim

+0

@orim: Вы уверены, что добавили знак процента в конце? – waka

+0

Да, и я знаю почему. Проблема заключается в том, что поплавки сбрасываются в varchar неправильно. – orim

0

Преобразовать значение FLOAT в DECIMAL затем VARCHAR с помощью CAST и использовать LIKE для выбора значения, начиная с 4045.

Запрос

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

Fiddle demo for reference

+0

Работает. Для моего примера это вернет только вторую строку. – orim

+0

Пожалуйста, проверьте демонстрацию скрипки. Там он возвращает вторую и третью строки. – Wanderer

+0

Да, см. Http://sqlfiddle.com/#!3/6f1d86/1 – orim

0

ЗАМЕНИТЬ избавиться от периода в поплавке, путем умножения на 1 любого 0 перед будут удалены.

SELECT f_value 
FROM your_table 
WHERE replace(f_value, '.', '') * 1 like '123%' 
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.00000
) 
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

Смежные вопросы