Как считать десятичные знаки в SQL?
У меня есть столбец X, который полон поплавков с десятичными знаками от 0 (без десятичных знаков) до 6 (максимум). Я могу рассчитывать на то, что нет поплавков с более чем 6 десятичными знаками. Учитывая это, как сделать новый столбец таким, чтобы он сообщал мне, сколько цифр после десятичного знака?
Я видел некоторые потоки, предлагающие использовать CAST для преобразования float в строку, а затем проанализировать строку, чтобы подсчитать длину строки, которая приходит после десятичного знака. Это лучший способ уйти?
6 ответов
вы можете использовать что-то вроде этого:
declare @v sql_variant
set @v=0.1242311
select SQL_VARIANT_PROPERTY(@v, 'Scale') as Scale
возвращает 7
.
Я попытался заставить вышеуказанный запрос работать с float
столбец, но не смог заставить его работать так, как ожидалось. Он работает только с sql_variant
столбец, как вы можете видеть здесь:http://sqlfiddle.com#!6 / 5c62c/2
Итак, я продолжил искать другой путь и строить на этом ответ, я понял:
SELECT value,
LEN(
CAST(
CAST(
REVERSE(
CONVERT(VARCHAR(50), value, 128)
) AS float
) AS bigint
)
) as Decimals
FROM Numbers
вот Скрипка SQL для проверить это: http://sqlfiddle.com/#!6/23d4f/29
чтобы объяснить эту маленькую причуду, вот модифицированная версия, которая будет обрабатывать случай, когда значение float не имеет десятичной части:
SELECT value,
Decimals = CASE Charindex('.', value)
WHEN 0 THEN 0
ELSE
Len (
Cast(
Cast(
Reverse(CONVERT(VARCHAR(50), value, 128)) AS FLOAT
) AS BIGINT
)
)
END
FROM numbers
вот сопровождающая SQL Fiddle:http://sqlfiddle.com#!6 / 10d54/11
поплавок просто представляет собой реальное число. Нет никакого смысла в количестве десятичных знаков реального числа. В частности, реальное число 3 может иметь шесть десятичных знаков, 3.000000, просто все десятичные знаки равны нулю.
У вас может быть преобразование отображения, которое не показывает правильные самые нулевые значения в десятичной дроби.
обратите внимание также, что причина, по которой существует максимум 6 десятичных знаков, заключается в том, что седьмой неточен, поэтому дисплей преобразование не будет фиксировать значение седьмого десятичного знака.
также обратите внимание, что поплавки хранятся в двоичном формате, и они фактически имеют двоичные места справа от двоичной точки. Десятичное отображение является аппроксимацией двоичного рационального в float-хранилище, которое, в свою очередь, является аппроксимацией вещественного числа.
Итак, дело в том, что на самом деле нет смысла, сколько десятичных знаков имеет значение float. Если вы делаете преобразование в строку (скажем, с помощью приведения), вы мог считать десятичные знаки. Это действительно будет лучший подход для того, что вы пытаетесь сделать.
этот поток также использует CAST, но я нашел ответ интересным:
http://www.sqlservercentral.com/Forums/Topic314390-8-1.aspx
DECLARE @Places INT
SELECT TOP 1000000 @Places = FLOOR(LOG10(REVERSE(ABS(SomeNumber)+1)))+1
FROM dbo.BigTest
и в ORACLE:
SELECT FLOOR(LOG(10,REVERSE(CAST(ABS(.56544)+1 as varchar(50))))) + 1 from DUAL
решение для Oracle, но у вас есть идея. trunc () удаляет десятичную часть в Oracle.
select *
from your_table
where (your_field*1000000 - trunc(your_field*1000000)) <> 0;
идея запроса: останутся ли десятичные дроби после умножения на 1 000 000.
вот еще один пример Oracle. Как я всегда предупреждаю пользователей, не являющихся Oracle, прежде чем они начнут кричать на меня и downvoting и т. д... подстрока и INSTRING являются стандартными функциями ANSI SQL и могут использоваться в любом SQL. Двойную таблицу можно заменить на любую другую таблицу или создать. Вот ссылка на блог SQL SERVER, из которого я скопировал код двойной таблицы: http://blog.sqlauthority.com/2010/07/20/sql-server-select-from-dual-dual-equivalent/
CREATE TABLE DUAL
(
DUMMY VARCHAR(1)
)
GO
INSERT INTO DUAL (DUMMY)
VALUES ('X')
GO
длина после точка или десятичное число возвращаются этим запросом. При необходимости str можно преобразовать в номер(str). Вы также можете получить длину строки до точки-десятичного знака-изменить код на длину (SUBSTR (str, 1, dot_pos)) -1 и удалить +1 в INSTR части:
SELECT str, LENGTH(SUBSTR(str, dot_pos)) str_length_after_dot FROM
(
SELECT '000.000789' as str
, INSTR('000.000789', '.')+1 dot_pos
FROM dual
)
/
SQL>
STR STR_LENGTH_AFTER_DOT
----------------------------------
000.000789 6
у вас уже есть ответы и примеры о литье и т. д...
Я ответил на это раньше, но я могу сказать из комментариев, что это немного непонятно. Со временем я нашел лучший способ выразить это.
рассмотрим pi как
(a) 3.141592653590
Это показывает pi как 11 десятичных знаков. Однако это было округлено до 12 знаков после запятой, как pi, до 14 цифр
(b) 3.1415926535897932
компьютер или база данных хранит значения в двоичном формате. Для одного прецизионного поплавка pi будет храниться как
(c) 3.141592739105224609375
это фактически округлено до ближайшее значение, которое может хранить одна точность, так же, как мы округлили в (a). Следующее наименьшее число, которое может хранить одна точность, -
(d) 3.141592502593994140625
Итак, когда вы пытаетесь подсчитать количество десятичных знаков, вы пытаетесь найти, сколько десятичных знаков, после чего все оставшиеся десятичные знаки будут равны нулю. Однако, поскольку число может быть округлено для его хранения, оно не представляет собой правильное значение.
числа также вводят ошибку округления как математическую операции выполняются, включая преобразование из десятичного в двоичный при вводе числа и преобразование из двоичного в десятичное при отображении значения.
вы не можете надежно найти количество десятичных знаков, которое имеет число в базе данных, потому что оно приближается к округлению для хранения в ограниченном объеме хранилища. Разница между реальным значением или даже точным двоичным значением в базе данных будет округлена до десятичного знака. Всегда может быть больше десятичные цифры, которые отсутствуют при округлении, поэтому вы не знаете, когда после нулей не будет больше ненулевых цифр.