如何在T-SQL中用逗号格式化数字?


198

我正在运行一些管理查询并sp_spaceused在SQL Server 2008中编译结果,以查看数据库中某些表的数据/索引空间比率。当然,结果中出现了各种各样的数字,我的眼睛开始蒙上一层阴影。如果我可以用逗号将所有这些数字格式化(987654321变为987,654,321),那将真的很方便。有趣的是,在我多年来一直使用SQL Server的过程中,这个问题从未出现过,因为大多数时候我都会在表示层进行格式化,但是在这种情况下,SSMS中的T-SQL结果就是表示。

我已经考虑过创建一个简单的CLR UDF来解决这个问题,但是看起来这应该在普通的旧T-SQL中是可行的。因此,我将在这里提出一个问题-您如何在香草T-SQL中进行数字格式化?


7
“报告->按表的磁盘使用情况”是否可以通过美观的方式满足您的需求?
Martin Smith 2010年

1
@Martin-真棒!甚至不知道那存在。我已经随身携带了一些DBA脚本近十年,所以我完全错过了。不过,我认为这个问题是基于stackoverflow的T-SQL知识库的重要组成部分,但是对于我的特定问题,这确实很方便。
mattmc3 2010年

8
使用SQL Server 2012 +可以使用FORMAT()函数。例如'#,##。000'msdn.microsoft.com/en
us/

Answers:


184

在SQL Server 2012及更高版本中,这将使用逗号格式化数字:

select format([Number], 'N0')

您也可以更改0为所需的小数位数。


16
这是自引入该format功能以来的最佳答案。
mattmc3

值得注意第三个(可选)参数culture
萨缪尔·科伦坡

OP指定了SQL Server 2008
foremaro

254

尽管我同意所有人(包括OP)的意见,包括OP表示应该在表示层中进行格式化,但是可以在T-SQL中通过强制转换为money,然后转换为来完成这种格式化varchar。不过,这的确包含了尾随的小数,可以使用来进行循环SUBSTRING

SELECT CONVERT(varchar, CAST(987654321 AS money), 1)

12
尽管我同意通常应在其他地方进行格式化,但我们所有人都认为日期格式化功能是理所当然的。如此处所示,可以插入逗号。+1。
EBarr 2010年

4
但是,这不适用于其他mony格式样式。例如,在瑞士,我们以以下形式写金钱:987'654'321.00该怎么做?
丹尼尔(Daniel)

6
您可以进行替换SELECT REPLACE(CONVERT(varchar,CAST(987654321 AS money),1),',','''')
Hoody 2013年

4
虽然我同意应尽可能在表示层中进行格式化,但在某些情况下(例如使用Ignite / DPA警报),肯定会收到的电子邮件就是表示层。将逗号放在这样的地方的唯一方法是通过SQL。在这些情况下,大量使用逗号特别有用。
PseudoToad

1
每个人都想告诉您“应该”做什么,但这并不是设计您自己的代码的目的。如果每个人都只做了“应该”做的事情,那么我们将失去那种发明精神和将事情拼凑在一起以最小的麻烦和精力快速解决问题的能力。
杰夫·格里斯瓦尔德

59

我建议使用Replace代替Substring来避免字符串长度问题:

REPLACE(CONVERT(varchar(20), (CAST(SUM(table.value) AS money)), 1), '.00', '')

3
即使货币兑换永远都不会改变,但我还是希望保证不会超出Replace在Substring上提供的范围。
肖恩(Sean)

48

对于SQL Server 2012+实现,您将能够使用FORMAT将字符串格式应用于非字符串数据类型。

在最初的问题中,用户要求使用逗号作为数千个分隔符的功能。在一个封闭的重复问题中,用户询问如何应用货币格式。以下查询显示了如何执行这两项任务。它还演示了文化的应用,使其成为更通用的解决方案(解决了Tsiridis Dimitris应用希腊特殊格式的功能)

-- FORMAT
-- http://msdn.microsoft.com/en-us/library/hh213505(v=sql.110).aspx
-- FORMAT does not do conversion, that's the domain of cast/convert/parse etc
-- Only accepts numeric and date/time data types for formatting. 
--
-- Formatting Types
-- http://msdn.microsoft.com/en-us/library/26etazsy.aspx

-- Standard numeric format strings
-- http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx
SELECT
    -- c => currency
    -- n => numeric
    FORMAT(987654321, N'N', C.culture) AS some_number
,   FORMAT(987654321, N'c', C.culture) AS some_currency
,   C.culture
FROM
    (
        -- Language culture names
        -- http://msdn.microsoft.com/en-us/library/ee825488(v=cs.20).aspx
        VALUES
            ('en-US')
        ,   ('en-GB')
        ,   ('ja-JP')
        ,   ('Ro-RO')
        ,   ('el-GR')
    ) C (culture);

上面的SQLFiddle


1
很大的一部分,这
将派上

1
小提琴坏了,它现在说String index out of range: 33
杰夫·普基特

1
@JeffPuckettII是的,很遗憾SQL Server的小提琴不再起作用。幸运的是,您应该能够将以上内容粘贴到连接到SQL Server 2012+的任何查询工具中
billinkc 16-10-28

20

演示1

演示添加逗号:

PRINT FORMATMESSAGE('The number is: %s', format(5000000, '#,##0'))
-- Output
The number is: 5,000,000

演示2

演示逗号和小数点。注意,如有必要,它会舍入最后一位数字。

PRINT FORMATMESSAGE('The number is: %s', format(5000000.759145678, '#,##0.00'))
-- Output
The number is: 5,000,000.76

兼容性

SQL Server 2012+


2
这是一个!与len(column)以及column一起使用-而我尝试的另一个2012+解决方案则没有。
Graham Laight

1
大!这是我一直在寻找的答案(用于T-SQL,包括SEDE使用
ashleedawg

10

请尝试以下查询:

SELECT FORMAT(987654321,'#,###,##0')

右小数点格式:

SELECT FORMAT(987654321,'#,###,##0.###\,###')

3
是的,现在我们拥有FORMAT函数的正确方法是SELECT format(123456789987654321,'###,##0'),或更简单地说,select format(123456789987654321, 'N0')就像@ThomasMueller回答的那样。
mattmc3 '18

FORMAT是一场性能噩梦-您开始使用它并依赖它,然后发现您的数据库无法扩展。现在,它内置了十二个功能,您无法逃脱它。切勿使用FORMAT。
Pxtl

9
SELECT REPLACE(CONVERT(varchar(20), (CAST(9876543 AS money)), 1), '.00', '')

输出= 9,876,543

并且您可以将9876543替换为您的列名。


7

尝试了上面的金钱技巧,这对于两位或更少有效数字的数值非常有用。我创建了自己的函数以小数点格式设置数字:

CREATE FUNCTION [dbo].[fn_FormatWithCommas] 
(
    -- Add the parameters for the function here
    @value varchar(50)
)
RETURNS varchar(50)
AS
BEGIN
    -- Declare the return variable here
    DECLARE @WholeNumber varchar(50) = NULL, @Decimal varchar(10) = '', @CharIndex int = charindex('.', @value)

    IF (@CharIndex > 0)
        SELECT @WholeNumber = SUBSTRING(@value, 1, @CharIndex-1), @Decimal = SUBSTRING(@value, @CharIndex, LEN(@value))
    ELSE
        SET @WholeNumber = @value

    IF(LEN(@WholeNumber) > 3)
        SET @WholeNumber = dbo.fn_FormatWithCommas(SUBSTRING(@WholeNumber, 1, LEN(@WholeNumber)-3)) + ',' + RIGHT(@WholeNumber, 3)



    -- Return the result of the function
    RETURN @WholeNumber + @Decimal

END

4

这属于对Phil Hunt的回答的评论,但可惜我没有代表。

要从数字字符串的末尾去除“ .00”,parsename非常方便。它标记句点分隔的字符串并返回指定的元素,从最右边的标记作为元素1开始。

SELECT PARSENAME(CONVERT(varchar, CAST(987654321 AS money), 1), 2)

产量为“ 987,654,321”


3

这是另一个T-SQL UDF

CREATE FUNCTION dbo.Format(@num int)
returns varChar(30)
As
Begin
Declare @out varChar(30) = ''

  while @num > 0 Begin
      Set @out = str(@num % 1000, 3, 0) + Coalesce(','+@out, '')
      Set @num = @num / 1000
  End
  Return @out
End

2
`/* Author: Tsiridis Dimitris */
/* Greek amount format. For the other change the change on replace of '.' & ',' */
CREATE FUNCTION dbo.formatAmount  (
@amtIn as varchar(20)
) RETURNS varchar(20)
AS
BEGIN 

return cast(REPLACE(SUBSTRING(CONVERT(varchar(20), CAST(@amtIn AS money), 1),1,
LEN(CONVERT(varchar(20), CAST(@amtIn AS money), 1))-3), ',','.')
 + replace(RIGHT(CONVERT(varchar(20), CAST(@amtIn AS money), 1),3), '.',',') AS VARCHAR(20))

END

SELECT [geniki].[dbo].[formatAmount]('9888777666555.44')`

1

这是我正在使用的一个标量函数,该函数修复了前面示例中的一些错误(上述),并且还处理了十进制值(达到指定的数字位数)(已编辑,还可以使用0和负数)。另一个需要注意的是,上面的强制转换为货币方法仅限于MONEY数据类型的大小,并且不适用于4位(或更多位)小数位数。该方法肯定更简单,但灵活性较差。

CREATE FUNCTION [dbo].[fnNumericWithCommas](@num decimal(38, 18), @decimals int = 4) RETURNS varchar(44) AS
BEGIN
    DECLARE @ret varchar(44)

    DECLARE @negative bit; SET @negative = CASE WHEN @num < 0 THEN 1 ELSE 0 END

    SET @num = abs(round(@num, @decimals)) -- round the value to the number of decimals desired
    DECLARE @decValue varchar(18); SET @decValue = substring(ltrim(@num - round(@num, 0, 1)) + '000000000000000000', 3, @decimals)
    SET @num = round(@num, 0, 1) -- truncate the incoming number of any decimals
    WHILE @num > 0 BEGIN
        SET @ret = str(@num % 1000, 3, 0) + isnull(','+@ret, '')
        SET @num = round(@num / 1000, 0, 1)
    END
    SET @ret = isnull(replace(ltrim(@ret), ' ', '0'), '0') + '.' + @decValue
    IF (@negative = 1) SET @ret = '-' + @ret

    RETURN @ret
END

GO

1

另一个UDF希望足够通用,并且不会对是否要舍入到小数位数进行假设:

CREATE FUNCTION [dbo].[fn_FormatNumber] (@number decimal(38,18))

RETURNS varchar(50)

BEGIN
    -- remove minus sign before applying thousands seperator
    DECLARE @negative bit
    SET @negative = CASE WHEN @number < 0 THEN 1 ELSE 0 END
    SET @number = ABS(@number)

    -- add thousands seperator for every 3 digits to the left of the decimal place
    DECLARE @pos int, @result varchar(50) = CAST(@number AS varchar(50))
    SELECT @pos = CHARINDEX('.', @result)
    WHILE @pos > 4
    BEGIN
        SET @result = STUFF(@result, @pos-3, 0, ',')
        SELECT @pos = CHARINDEX(',', @result)
    END

    -- remove trailing zeros
    WHILE RIGHT(@result, 1) = '0'
        SET @result = LEFT(@result, LEN(@result)-1)
    -- remove decimal place if not required
    IF RIGHT(@result, 1) = '.'
        SET @result = LEFT(@result, LEN(@result)-1)

    IF @negative = 1
        SET @result = '-' + @result

    RETURN @result
END

0
/*
  #------------------------------------------------------------------------#
  #            SQL Query Script                                            #
  #            ----------------                                            #
  # Funcion.:  dbo.fn_nDerecha ( Numero, Pos_Enteros, Pos_Decimales )      #
  #    Numero        : es el Numero o Valor a formatear                    #
  #    Pos_Enteros   : es la cantidad posiciones para Enteros              #
  #    Pos_Decimales : es la cantidad posiciones para Decimales            #
  #                                                                        #
  # OBJETIVO:  Formatear los Numeros con Coma y Justificado a la Derecha   #
  #  Por Ejemplo:                                                          #
  #   dbo.fn_nDerecha ( Numero, 9, 2 )         Resultado = ---,---,--9.99  #
  #               dado  Numero = 1234.56       Resultado =       1,234.56  #
  #               dado  Numero = -1.56         Resultado =          -1.56  #
  #               dado  Numero = -53783423.56  Resultado = -53,783,423.56  #
  #                                                                        #
  # Autor...:  Francisco Eugenio Cabrera Perez                             #
  # Fecha...:  Noviembre 25, 2015                                          #
  # Pais....:  Republica Dominicana                                        #
  #------------------------------------------------------------------------#
*/



CREATE FUNCTION [dbo].[fn_nDerecha]
(
    -- Agregue Argumentos, para personalizar la funcion a su conveniencia
    @Numero_str    varchar(max)
   ,@Pos_Enteros   int
   ,@Pos_Decimales int
)
RETURNS varchar(max)
AS
BEGIN
  --  Declare la variable del RETURN aqui, en este caso es RESULT
  declare @RESULTADO varchar(max)
  set     @RESULTADO = '****'

  -----------------------------------------------  --
  declare @Numero_num numeric(28,12)
  set     @Numero_num =
  (
  case when isnumeric(@Numero_str) = 0 
       then 0
       else round (convert( numeric(28,12), @Numero_str), @Pos_Decimales)
  end
  )
  --  -----------------------------------------------  --
  --  Aumenta @Pos_Enteros de @RESULTADO,
  --      si las posiciones de Enteros del dato @Numero_str es Mayor...
  --
  declare   @Num_Pos_Ent int
  set       @Num_Pos_Ent = len ( convert( varchar, convert(int, abs(@Numero_num) ) ) )
  --
  declare   @Pos_Ent_Mas int
  set       @Pos_Ent_Mas =
  (
  case when @Num_Pos_Ent > @Pos_Enteros
       then @Num_Pos_Ent - @Pos_Enteros
       else 0
  end
  )
  set       @Pos_Enteros = @Pos_Enteros + @Pos_Ent_Mas
  --
  --  -----------------------------------------------  --
  declare @p_Signo_ctd       int
  set     @p_Signo_ctd       = (case when @Numero_num < 1 then 1 else 0 end)
  --
  declare @p_Comas_ctd       int
  set     @p_Comas_ctd       = ( @Pos_Enteros - 1 ) / 3
  --
  declare @p_Punto_ctd       int
  set     @p_Punto_ctd       = (case when @Pos_Decimales > 0 then 1 else 0 end)
  --
  declare @p_input_Longitud  int
  set     @p_input_Longitud  = ( @p_Signo_ctd + @Pos_Enteros ) +
                                 @p_Punto_ctd + @Pos_Decimales
  --
  declare @p_output_Longitud int
  set     @p_output_Longitud = ( @p_Signo_ctd + @Pos_Enteros   + @p_Comas_ctd )
                             + ( @p_Punto_ctd + @Pos_Decimales )
  --
  --  ===================================================================  --


  declare @Valor_str varchar(max)
  set     @Valor_str = str(@Numero_num, @p_input_Longitud, @Pos_Decimales)

  declare @V_Ent_str varchar(max)
  set     @V_Ent_str = 
  (case when @Pos_Decimales > 0 
        then substring( @Valor_str, 0, charindex('.', @Valor_str, 0) )
        else            @Valor_str end)
  --
  declare @V_Dec_str varchar(max)
  set     @V_Dec_str = 
  (case when @Pos_Decimales > 0 
        then '.' + right(@Valor_str, @Pos_Decimales)
        else '' end)
  --
  set @V_Ent_str = convert(VARCHAR, convert(money, @V_Ent_str), 1) 
  set @V_Ent_str = substring( @V_Ent_str, 0, charindex('.', @V_Ent_str, 0) )
  --


  set @RESULTADO    = @V_Ent_str + @V_Dec_str 
  --
  set @RESULTADO = ( replicate( ' ', @p_output_Longitud - len(@RESULTADO) ) + @RESULTADO )
  --

  --  ===================================================================  -

-================================================ ==================-

  RETURN @RESULTADO
END

  --  ===================================================================  --

/ *此函数需要3个参数:第一个参数是@Numero_str,该数字作为数据输入,其他两个参数指定如何格式化输出信息,这些参数是@Pos_Enteros和@Pos_Decimales,它们指定多少您要显示作为输入参数传递的数字的整数和小数位。* /


0

对于不包含FORMAT函数的2012年之前的SQL Server,请创建以下函数:

CREATE FUNCTION FormatCurrency(@value numeric(30,2))
    RETURNS varchar(50)
    AS
    BEGIN
        DECLARE @NumAsChar VARCHAR(50)
        SET @NumAsChar = '$' + CONVERT(varchar(50), CAST(@Value AS money),1)
        RETURN @NumAsChar
    END 

select dbo.FormatCurrency(12345678)返回$ 12,345,678.00

如果只需要逗号,请删除$。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.