Sql server 如何在T-SQL中使用逗号格式化数字?
我正在运行一些管理查询,并从SQL Server 2008中的Sql server 如何在T-SQL中使用逗号格式化数字?,sql-server,tsql,Sql Server,Tsql,我正在运行一些管理查询,并从SQL Server 2008中的sp_spaceused编译结果,以查看数据库中某些表的数据/索引空间比率。当然,我在结果中得到了各种各样的大数字,我的眼睛开始变得明亮起来。如果我能用逗号格式化所有这些数字(987654321变为987654321),那将非常方便。有趣的是,在我使用SQL Server这么多年的时间里,这个问题从来没有出现过,因为大多数时候我都是在表示层进行格式化,但在这种情况下,SSMS中的T-SQL结果就是表示层 我曾考虑过创建一个简单的CLR
sp_spaceused
编译结果,以查看数据库中某些表的数据/索引空间比率。当然,我在结果中得到了各种各样的大数字,我的眼睛开始变得明亮起来。如果我能用逗号格式化所有这些数字(987654321变为987654321),那将非常方便。有趣的是,在我使用SQL Server这么多年的时间里,这个问题从来没有出现过,因为大多数时候我都是在表示层进行格式化,但在这种情况下,SSMS中的T-SQL结果就是表示层
我曾考虑过创建一个简单的CLR UDF来解决这个问题,但似乎这应该可以在普通的旧T-SQL中实现。因此,我将在这里提出一个问题-如何在香草T-SQL中进行数字格式设置?虽然我同意包括OP在内的所有人的观点,他们认为格式设置应该在表示层中完成,但这种格式设置可以在T-SQL中通过转换为
money
然后转换为varchar
。不过,这确实包括可以使用子字符串
循环的尾随小数
SELECT CONVERT(varchar, CAST(987654321 AS money), 1)
尝试了上面的金钱技巧,这对于具有两个或更少有效数字的数值非常有效。我创建了自己的函数,用小数格式化数字:
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
我建议替换子字符串以避免字符串长度问题:
REPLACE(CONVERT(varchar(20), (CAST(SUM(table.value) AS money)), 1), '.00', '')
下面是另一个t-SQLUDF
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
对于SQL Server 2012+实现,您将能够使用将字符串格式应用于非字符串数据类型 在最初的问题中,用户要求能够使用逗号作为数千个分隔符。在一次访问中,用户询问如何应用货币格式。以下查询显示如何执行这两项任务。它还演示了如何应用区域性使其成为更通用的解决方案(解决Tsiridis Dimitris的函数以应用希腊特殊格式)
对于上面的这里是我正在使用的一个标量函数,它修复了前面示例(上面)中的一些错误,并且还处理十进制值(到指定的#位数)(编辑后也可以处理0和负数)。另一个注意事项是,上面的cast-as-money方法仅限于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
CREATE函数[dbo]。[fnNumericWithCommas](@num decimal(38,18),@decimals int=4)将varchar(44)返回为
开始
声明@ret varchar(44)
声明@负位;当@num<0时设置@negative=CASE,然后设置1或0结束
设置@num=abs(舍入(@num,@decimals))--将值舍入到所需的小数位数
声明@decValue varchar(18);设置@decValue=substring(ltrim(@num-round(@num,0,1))+'000000000000000000',3,@decimals)
设置@num=round(@num,0,1)--截断任何小数的传入数字
当@num>0开始时
SET@ret=str(@num%1000,3,0)+isnull(“,”+@ret,”)
设置@num=round(@num/1000,0,1)
结束
设置@ret=isnull(替换(ltrim(@ret),“”,'0'),'0')+'.+@decValue
如果(@negative=1)设置@ret='-'+@ret
返回@ret
结束
去
另一个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
创建函数[dbo].[fn_FormatNumber](@number decimal(38,18))
返回varchar(50)
开始
--在应用分隔符之前删除减号
声明@负位
当@number<0时设置@negative=CASE,然后设置1或0结束
设置@number=ABS(@number)
--在小数点左侧每3位添加千位分隔符
声明@pos int,@result varchar(50)=强制转换(@number为varchar(50))
选择@pos=CHARINDEX('.',@result)
而@pos>4
开始
设置@result=STUFF(@result,@pos-3,0,,'))
选择@pos=CHARINDEX(“,”,@result)
结束
--删除尾随零
而右(@result,1)='0'
设置@result=LEFT(@result,LEN(@result)-1)
--如果不需要,请删除小数位
如果正确(@result,1)='。'
设置@result=LEFT(@result,LEN(@result)-1)
如果@负=1
设置@result='-'+@result
返回@result
结束
在SQL Server 2012及更高版本中,这将使用逗号格式化数字:
select format([Number], 'N0')
您还可以将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 )
--
-- =================================================================== -
/*
此函数需要3个参数:第一个参数是@Numero_str,该参数将数字作为数据输入,另外2个参数指定如何为输出格式化信息,这些参数是@Pos_Enteros和@Pos_Decimales,它们指定要为作为输入参数传递的数字显示的整数和小数位数。
*/演示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+
SELECT REPLACE(CONVERT(varchar(20), (CAST(9876543 AS money)), 1), '.00', '')
输出=9876543
您可以用您的列名替换9876543。这属于对的回复中的注释,但遗憾的是,我没有代表 要去掉数字字符串末尾的“.00”,parsename非常方便。 它标记以句点分隔的字符串并返回指定的元素,从最右边的标记开始,作为元素1
SELECT PARSENAME(CONVERT(varchar, CAST(987654321 AS money), 1), 2)
产生“987654321”请尝试以下查询:
SELECT FORMAT(987654321,'#,###,##0')
带右小数点的格式:
SELECT FORMAT(987654321,'#,###,##0.###\,###')
对于2012年之前不包含FORMAT函数的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
选择dbo.FormatCurrency(12345678)
返回$12345678.00
如果您只需要逗号,请删除$ “报表->磁盘使用情况表”是否以一种美观的方式满足了您的需要?@Martin-真是太棒了!我甚至不知道那是存在的。我带了som
SELECT FORMAT(987654321,'#,###,##0')
SELECT FORMAT(987654321,'#,###,##0.###\,###')
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