【问题标题】:Issue converting JSON string into decimal将 JSON 字符串转换为十进制的问题
【发布时间】:2018-12-14 00:37:41
【问题描述】:

这个问题可能会在许多线程上回答,但我无法找到针对我的问题的答案。

问:我从 API(json 格式)获取数据,其中所有列都以字符串形式出现并插入到一个表中,该表将所有列都作为字符串并用作源表。

现在,我正在尝试将数据从该源转换到目标,并进行所有必要的转换以将数据插入到目标表中。但是十进制 (16,8) 转换失败。

我最后调试了问题,发现在从 API 获取数据的过程中,API 将数据返回为 json 格式,并将值转换为一些不寻常的格式。

例如0.00007 转换为 7E-05,这发生在许多其他行上。

我知道我可以在 API 实现级别解决这个问题。但我要求在 SQL 服务器端解决这个问题。所以我需要一个将 7E-05 转换为 0.00007 的解决方案。

【问题讨论】:

  • 从源头上解决这个问题是处理这个问题的正确方法。在 sql 中执行此操作需要一些丑陋的字符串操作。
  • 嗯。这种形式一致吗? 5 会显示什么? 15? 1.345?
  • 另请注意,当您再次插入指定的列时,从 JSON 转换为浮点/十进制将转换回字符串格式。该值将始终为字符串类型还是始终为十进制类型?有很多幕后的转换正在发生。最好将您的目标表数据类型设置为它实际预期保存的任何数据类型。如果值是小数,则将其设为小数列。
  • 大家好,感谢您的快速回复。到目前为止,SQL 部分解决了我的问题。让我告诉你从字符串中提取所有内容为字符串的原因。作为解决方案的一部分,API 实现是我们不希望让我们的 cron 作业无法获取数据的地方,因为我们无法控制来自供应商的数据,并且我们的供应商由于市场动态的变化而经常更改系统。因此,我们很容易在 sql 级别实现大部分内容,我们可以轻松调试,如果需要,可以在生产中部署任何更改,停机时间最少且易于处理。
  • @RahulNeekhra 这是一个非常常见的用例。最推荐的是一个容错的临时表。这是您导入的目标。从这个暂存表中,您可以进行任何类型的验证/转换并将数据转换为实际目标。顺便说一句:说“谢谢”很友好,但如果解决了这个问题,投票和接受就更友好了;-D

标签: sql sql-server tsql casting decimal


【解决方案1】:

尝试类似:

SELECT CAST(CAST(@t AS FLOAT) AS DECIMAL(16,8))

结果:

0.00007000

CASTFLOAT,然后到 DECIMAL

【讨论】:

  • 好点。如果 JSON 填充或包含空字符,可能最好修剪变量。
  • 转换为数字数据类型时,任何空格都会被删除。只是不需要修剪。也许需要一个 try_cast 但否则应该没问题。
  • 我会推荐TRY_CAST,但这是 SQL 2012+ 的功能。如果 2008R2 或更低版本,执行相同操作的自定义标量函数可能会很好。
  • @Shawn,对于 2012 年以下的版本,使用 XML 的演员表有一个非常好的技巧:SELECT CAST('32' AS XML).value('. cast as xs:int?','int') 这可以完全内联完成...尝试用错误的值替换 32,您只需获取NULL
【解决方案2】:

这种不寻常的格式是一种相当常见的科学记数法Wikipedia, read section "E-notation"

您会看到E 和一个表示指数的数字。

"1E2"  = 1 * 10^2 = 100
"1E-2" = 1 * 10^(-2) = 0.01

试试这个:

DECLARE @tbl TABLE(Numberstring VARCHAR(100));
INSERT INTO @tbl VALUES('100'),('1E2'),('1E-2'),('7E-05');
SELECT Numberstring
      ,CAST(Numberstring AS FLOAT) 
      ,CAST(CAST(Numberstring AS FLOAT) AS DECIMAL(20,10)) 
FROM @tbl;

结果

100     100     100.0000000000
1E2     100     100.0000000000
1E-2    0,01    0.0100000000
7E-05   7E-05   0.0000700000

您可以看到,FLOAT 类型本身将显示科学计数法中的最后一个,而转换为 DECIMAL 将返回您期望的数字。

我会很高兴有一个赞成票,但你应该接受肖恩的回答,因为它比我早:-D

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多