从存储为字符串的数字中提取分数

时间:2013-01-15 15:02:06

标签: sql string extract fractions

我在这个数据库中有一个字段,存储数字如下:

  • 80 1/4
  • 20 1/8
  • 20
  • 36 15/16
  • 44 1/8
  • 93 7/8
  • 89 1/8

我正在尝试将这些转换为完整的小数,以便我可以将它们添加起来。我一直试图通过从数字中提取分数,将其转换为小数,然后将其添加到整数来尝试这样做。我在提取分子时遇到了一些重大问题。分母已使用以下方法提取:

CASE WHEN CHARINDEX('/',Fraction) > 0 THEN RIGHT(Faction,(LEN(Fraction) - (CHARINDEX('/',Fraction)))) ELSE NULL END AS [Denominator]

我不确定这是否是最有效的方法,但似乎有效。

我试图用这种方法拉出分子:

CASE WHEN Charindex('/', Fraction) > 0 THEN LEFT(RIGHT(Fraction, Len(Fraction) - Charindex(' ',Fraction)), CHARINDEX('/',Fraction) - 1) ELSE NULL END AS [Numerator]

但这只是给了我自己的分数。我不确定SQL在LEFT中是否存在RIGHT问题,因为它似乎没有做任何事情,或者更可能的是,我的代码搞砸了。

有人有什么想法吗?

谢谢!

4 个答案:

答案 0 :(得分:2)

你几乎做对了:你正在计算错误传递给LEFT的长度。你需要考虑空间的位置。

而不是

CHARINDEX('/',Fraction) - 1

长度应为

CHARINDEX('/',Fraction) - CHARINDEX(' ',Fraction) - 1

整体表达式应如下所示:

CASE WHEN Charindex('/', Fraction) > 0 THEN LEFT(RIGHT(Fraction, Len(Fraction) - Charindex(' ',Fraction)), CHARINDEX('/',Fraction) - CHARINDEX(' ',Fraction) - 1) ELSE NULL END AS [Numerator]

Link to demo on sqlfiddle.

答案 1 :(得分:1)

这应该有效。我已将CHARINDEX函数移到APPLY内部,试图让它更清晰

WITH Data AS
(   SELECT  Fraction
    FROM    (VALUES
                ('80 1/4'),
                ('20 1/8'),
                ('20'),
                ('36 15/16'),
                ('44 1/8'),
                ('93 7/8'),
                ('89 1/8')
            ) t (Fraction)
), Workings AS
(   SELECT  Fraction,
            WholeNumber = CAST(CASE WHEN FractionIndex = 0 THEN Fraction ELSE LEFT(Fraction, SpaceIndex) END AS FLOAT),
            Numerator = CAST(CASE WHEN FractionIndex > 0 THEN SUBSTRING(Fraction, SpaceIndex, FractionIndex - SpaceIndex) END AS FLOAT),
            Demonimator = CAST(CASE WHEN FractionIndex > 0 THEN SUBSTRING(Fraction, FractionIndex + 1, LEN(Fraction)) END AS FLOAT)
    FROM    Data
            CROSS APPLY 
            (   SELECT  FractionIndex = CHARINDEX('/', Fraction),
                        SpaceIndex = CHARINDEX(' ', Fraction)
            ) f
)
SELECT  *,
        [Decimal] = CAST(WholeNumber + COALESCE(Numerator / Demonimator, 0) AS FLOAT)
FROM    Workings

答案 2 :(得分:0)

您可以尝试以下方法:

with t as (select '80 123/456' as val)
select (case when val like '% %/%'
             then cast(left(val, charindex(' ', val)) as float) +
                  (cast(SUBSTRING(val, charindex(' ', val), CHARINDEX('/', val) - charindex(' ', val)) as float) /
                   CAST(SUBSTRING(val, charindex('/', val)+1, 100) as int)
                  )
             else cast(val as float)
        end)
from t

答案 3 :(得分:0)

只需将变量替换为您的列名称,并将其放置在您的“CHARINDEX('/',Fraction)> 0”为真的case语句部分中。

Declare @num varchar(50) = '1004 1/3'

--      Numerator
Select  Left(Right(@num,Len(@num)-CharIndex(' ',@num)),CharIndex('/',Right(@num,Len(@num)-CharIndex(' ',@num)))-1)
--      Denominator
Select  Right(Right(@num,Len(@num)-CharIndex(' ',@num)),Len(Right(@num,Len(@num)-CharIndex(' ',@num)))-CharIndex('/',Right(@num,Len(@num)-CharIndex(' ',@num))))