J'exécute des requêtes administratives et compile les résultats de sp_spaceused
dans SQL Server 2008 pour examiner les ratios d'espace données/index de certaines tables de ma base de données. Bien sûr, je reçois toutes sortes de chiffres en grand nombre dans les résultats et mes yeux commencent à briller de mille feux. Ce serait vraiment pratique si je pouvais formater tous ces nombres avec des virgules (987654321 devient 987,654,321). C'est drôle que pendant toutes les années où j'ai utilisé SQL Server, ce problème ne se soit jamais posé car je formais la plupart du temps au niveau de la couche de présentation, mais dans ce cas, le résultat T-SQL dans SSMS est la présentation.
J'ai envisagé de créer simplement un fichier UDF CLR simple pour résoudre ce problème, mais il semble que cela devrait être réalisable dans le vieux T-SQL. Je vais donc poser la question suivante: comment formater le format numérique dans Vanilla T-SQL?
Dans SQL Server 2012 et versions ultérieures, cela formate un nombre avec des virgules:
select format([Number], 'N0')
Vous pouvez également remplacer 0
par le nombre de décimales souhaité.
Bien que je sois d’accord avec tout le monde, y compris le PO, qui dit que le formatage doit être effectué dans la couche de présentation, ce formatage peut être effectué dans T-SQL en convertissant en money
, puis en convertissant en varchar
. Cela inclut les décimales de fin, cependant, qui pourraient être bouclées avec SUBSTRING
.
SELECT CONVERT(varchar, CAST(987654321 AS money), 1)
Je vous recommande de remplacer à la place de Substring pour éviter les problèmes de longueur de chaîne:
REPLACE(CONVERT(varchar(20), (CAST(SUM(table.value) AS money)), 1), '.00', '')
Pour les implémentations de SQL Server 2012+, vous pourrez utiliser le FORMAT pour appliquer le formatage de chaîne à des types de données autres que des chaînes.
Dans la question initiale, l'utilisateur avait demandé la possibilité d'utiliser des virgules comme séparateurs de milliers. Dans un question fermée en double , l'utilisateur avait demandé comment il pouvait appliquer le formatage monétaire. La requête suivante montre comment effectuer les deux tâches. Cela démontre également l'application de la culture pour en faire une solution plus générique (adressant la fonction de Tsiridis Dimitris d'appliquer un formatage spécial grec)
-- 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 pour ce qui précède
Montre comment ajouter des virgules:
PRINT FORMATMESSAGE('The number is: %s', format(5000000, '#,##0'))
-- Output
The number is: 5,000,000
Montre des virgules et des points décimaux. Notez qu’il arrondit le dernier chiffre si nécessaire.
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', '')
sortie = 9 876 543
et vous pouvez remplacer 9876543 par votre nom de colonne.
Veuillez essayer avec la requête ci-dessous:
SELECT FORMAT(987654321,'#,###,##0')
Format avec point décimal à droite:
SELECT FORMAT(987654321,'#,###,##0.###\,###')
J'ai essayé le truc d'argent ci-dessus, et cela fonctionne très bien pour les valeurs numériques avec deux chiffres significatifs ou moins. J'ai créé ma propre fonction pour formater des nombres avec des décimales:
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
Cela appartient à un commentaire de la réponse de Phil Hunt mais hélas je n'ai pas le représentant.
Pour supprimer le ".00" de la fin de votre chaîne numérique, le parsename est extrêmement pratique. Il marque les chaînes délimitées par des périodes et renvoie l'élément spécifié, en commençant par le jeton le plus à droite en tant qu'élément 1.
SELECT PARSENAME(CONVERT(varchar, CAST(987654321 AS money), 1), 2)
Les rendements "987,654,321"
voici un autre 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
`/* 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')`
Voici une fonction scalaire que j'utilise qui corrige quelques bugs dans un exemple précédent (ci-dessus) et gère également les valeurs décimales (en fonction du nombre de chiffres spécifié) (EDITED fonctionne également avec les nombres 0 et négatifs). Autre remarque, la méthode de conversion en tant qu’argent ci-dessus est limitée à la taille du type de données MONEY et ne fonctionne pas avec 4 décimales (ou plus). Cette méthode est nettement plus simple mais moins 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
Un autre fichier UDF qui, espérons-le, est suffisamment générique et ne suppose pas que vous voulez arrondir à un nombre spécifique de décimales:
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
/*
#------------------------------------------------------------------------#
# 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
-- =================================================================== --
/ * Cette fonction nécessite 3 arguments: le premier argument est le @Numero_str dont le numéro est une entrée de données et les 2 autres arguments spécifient comment l'information sera formatée pour la sortie, ces arguments sont @Pos_Enteros et @Pos_Decimales qui spécifient combien Entiers et décimales que vous souhaitez afficher pour le nombre que vous transmettez en tant qu'argument d'entrée. * /