sql-server - numero - formato 2 decimales sql server
¿Cómo formateo un número con comas en T-SQL? (14)
Demo 1
Demuestra agregar comas:
PRINT FORMATMESSAGE(''The number is: %s'', format(5000000, ''#,##0''))
-- Output
The number is: 5,000,000
Demo 2
Demuestra comas y puntos decimales. Observe que redondea el último dígito si es necesario.
PRINT FORMATMESSAGE(''The number is: %s'', format(5000000.759145678, ''#,##0.00''))
-- Output
The number is: 5,000,000.76
Compatibilidad
SQL Server 2012+
.
Estoy ejecutando algunas consultas administrativas y recopilando resultados de sp_spaceused
en SQL Server 2008 para ver las proporciones de espacio de índice / datos de algunas tablas en mi base de datos. Por supuesto, estoy obteniendo todo tipo de números grandes en los resultados y mis ojos están empezando a desvanecerse. Sería realmente conveniente si pudiera formatear todos esos números con comas (987654321 se convierte en 987,654,321). Es curioso que en todos los años que he usado SQL Server, este problema nunca haya surgido ya que la mayoría de las veces estaría formateando en la capa de presentación, pero en este caso el resultado de T-SQL en SSMS es la presentación.
Consideré simplemente crear un UDF de CLR simple para resolver esto, pero parece que esto debería ser posible en el viejo y simple T-SQL. Entonces, plantearé la pregunta aquí: ¿cómo se formatea numéricamente en T-SQL vainilla?
Aquí hay una función escalar que estoy usando que corrige algunos errores en un ejemplo anterior (arriba) y también maneja valores decimales (al número de dígitos especificado) (EDITADO también funciona con 0 y números negativos). Otra nota, el método de reparto como dinero anterior está limitado al tamaño del tipo de datos MONEY, y no funciona con 4 (o más) dígitos decimales. Ese método es definitivamente más simple pero menos flexible.
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
En SQL Server 2012 y superior, esto formateará un número con comas:
select format([Number], ''N0'')
También puede cambiar 0
a la cantidad de decimales que desee.
Esto pertenece a un comentario de la respuesta de , pero lamentablemente no tengo el representante.
Para quitar el ".00" del final de la cadena de números, parsename es súper útil. Token cadenas de caracteres delimitadas por períodos y devuelve el elemento especificado, comenzando por el token de la derecha como elemento 1.
SELECT PARSENAME(CONVERT(varchar, CAST(987654321 AS money), 1), 2)
Rinde "987,654,321"
Intenté el truco de dinero anterior, y esto funciona muy bien para valores numéricos con dos o menos dígitos significativos. Creé mi propia función para formatear números con decimales:
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
Intente con la siguiente consulta:
SELECT FORMAT(987654321,''#,###,##0'')
Formatear con el punto decimal derecho:
SELECT FORMAT(987654321,''#,###,##0.###/,###'')
Otra UDF que, afortunadamente, es lo suficientemente genérica y no hace suposiciones sobre si desea redondear a un número específico de decimales:
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
Para las implementaciones de SQL Server 2012+, tendrá la capacidad de utilizar FORMAT para aplicar formato de cadenas a tipos de datos que no sean cadenas.
En la pregunta original, el usuario había solicitado la posibilidad de usar comas como separadores de miles. En una pregunta cerrada como duplicada , el usuario había preguntado cómo podían aplicar el formato de moneda. La siguiente consulta muestra cómo realizar ambas tareas. También demuestra la aplicación de la cultura para hacer de esta una solución más genérica (abordando la función de Tsiridis Dimitris para aplicar el formato especial griego)
-- 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 para el anterior
Recomiendo reemplazar en lugar de subcadena para evitar problemas de longitud de cadena:
REPLACE(CONVERT(varchar(20), (CAST(SUM(table.value) AS money)), 1), ''.00'', '''')
Si bien estoy de acuerdo con todo el mundo, incluido el OP, que dice que el formateo debe hacerse en la capa de presentación, este formato se puede realizar en T-SQL al convertirlo en money
y luego convertirlo a varchar
. Esto incluye los decimales finales, sin embargo, que se pueden SUBSTRING
con SUBSTRING
.
SELECT CONVERT(varchar, CAST(987654321 AS money), 1)
aquí hay otro UDF t-sql
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 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
-- =================================================================== --
/ * Esta función necesita 3 argumentos: el primer argumento es @Numero_str que el Número como entrada de datos, y los otros 2 argumentos especifican cómo se formateará la información para el resultado, esos argumentos son @Pos_Enteros y @Pos_Decimales que especifican cuántos Números enteros y decimales que desea mostrar para el número que pasa como argumento de entrada. * /
SELECT REPLACE(CONVERT(varchar(20), (CAST(9876543 AS money)), 1), ''.00'', '''')
salida = 9,876,543
y puede reemplazar 9876543 por su nombre de columna.
`/* 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'')`