使用任意小数位数格式化 SQL 数值查询结果

Posted

技术标签:

【中文标题】使用任意小数位数格式化 SQL 数值查询结果【英文标题】:Formatting an SQL numeric query result with an arbitrary number of decimal places 【发布时间】:2009-03-16 22:44:06 【问题描述】:

我有一个包含这两列的数据库表:

金额:数字 (18,0) DecimalPlaces:数字 (18,0)

此表可以存储各种货币的金额,从金额中删除小数位(我无法更改此数据模型)。例如,可能有两行这样的:

1290, 2(这是 12.90 英镑,需要显示为“12.90”) 3400, 0(这是3400日元,需要显示为“3400”)

我需要一个针对 Oracle 和 SQL Server 的 SQL 查询,它将使用正确的小数位数格式化每个金额,并保留所有尾随零,如上图所示。我无法使用存储过程、报告工具或 Excel。

【问题讨论】:

Tom H. 实际上引导我走上正义之路,他的建议是格式最好留给客户。所以我最终通过重构客户端来解决这个问题。它使查询引擎更加复杂,但不如使用特定于大型数据库的查询那样复杂。 哇,10k 浏览量和零点赞 - 当然有一个徽章 - 也许是“着名的令人失望的问题”? :-) 【参考方案1】:

您的问题是,没有一种简单的方法可以在一个查询中同时为 SQLServer 和 Oracle 执行此操作。

对 SQLServer 执行此操作的正确方法是使用 STR:

Select STR(Amount, 18, DecimalPlaces) from myTable;

对 Oracle 执行此操作的正确方法是使用 to_char:

SELECT to_char (amount, '99999999999999.'||rpad('',DecimalPlaces, '0')) 
from MyTable;

jms 和 Andrew 提供的查询在 Oracle 查询中不起作用,因为 Oracle SQL 使用 LENGTH() 而不是 LEN()。 Oracle 使用 to_char() 而不是 Cast()。

【讨论】:

【参考方案2】:

到目前为止,我能想到的最好的是:

select Amount/power(10, DecimalPlaces) from MyTable

但它并不完全符合我的要求:

Oracle:去除尾随零,因此 US$15.00 看起来像“15”,而不是“15.00” SQL Server:添加了大量额外的尾随零,因此 $23.99 看起来像“23.99000000000”而不是“23.99”

【讨论】:

我发现如果我使用这个: convert(varchar, cast(Amount/power(10, DecimalPlaces) as money), 2) ... 那么我得到四位小数而不是 11 ,看起来更好。 格式化确实更适合前端处理。 同意,但在我的情况下,前端不知道每行的小数位数,因此无法执行必要的格式化。 SELECT CAST(@Amount/power(10, @DecimalPlaces) A​​S decimal(18,2))【参考方案3】:

怎么样?

选择 12345 数量, 2 个小数位, substr( to_char( 12345 ), 1, 长度 (to_char( 12345 ) ) - 2 ) || '。 || substr( to_char( 12345 ), -2 ) 双重结果 /

     amount decimalPlaces result
 ---------- ------------- ------
     12345              2 123.45

【讨论】:

感谢这个想法。不幸的是,它留下了一个尾随的“。”如果 decimalPlaces = 0,但这很容易通过替换 '.' 来解决在你的表达式中使用 substr('.', 2 - decimalplaces)。【参考方案4】:

这很粗略,但适用于 SQL 服务器上的当前输入。

select 
    substring(
     CAST(
      CAST(
        (amount *  power(-0.100000000000000000,decimalPlaces*1.000000000000000000)) as numeric(36,18)
      )as varchar(30)
     )
    ,1,len(cast(amount as varchar(20))) + (CASE WHEN decimalPlaces = 0 THEN 0 ELSE 1 END )) 

from
 myTable

【讨论】:

我的结果窗口中没有尾随零。 这就是这种方法的问题:包含 (1200, 2) 的行将显示为“12”而不是“12.00”。 我明白了。我会继续尝试,但如果您将其添加到示例数据中,它可能会对其他人有所帮助。【参考方案5】:

在 SQL 服务器中你可以:

select stuff(convert(varchar,amount) ,
         len(convert(varchar,amount)) - DecimalPlaces - 1, 0, ".")

【讨论】:

【参考方案6】:

Martlark 对 Oracle 的回答让我想到了这个 SQL Server 解决方案:

select
  left(cast(Amount as varchar), len(cast(Amount as varchar)) - DecimalPlaces) +
  left('.', DecimalPlaces) +
  right(cast(OriginalCurrencyAmount as varchar), DecimalPlaces
) as FormattedAmount
from MyTable

【讨论】:

以上是关于使用任意小数位数格式化 SQL 数值查询结果的主要内容,如果未能解决你的问题,请参考以下文章

怎么保留一位小数?

mysql查询结果单位换算后小数位数的保留方式

SQL中的小数点后的输入位数.

Oracle中关于处理小数点位数的几个函数,取小数位数,Oracle查询函数

格式化查询以在 Oracle SQL 中显示浮点小数

SQL怎么把小数转换为百分比?