Wie formatiere ich eine Zahl mit Kommas in T-SQL?

198

Ich führe einige administrative Abfragen aus und kompiliere Ergebnisse aus sp_spaceusedSQL Server 2008, um die Daten- / Indexbereichsverhältnisse einiger Tabellen in meiner Datenbank zu überprüfen. Natürlich bekomme ich alle möglichen großen Zahlen in den Ergebnissen und meine Augen beginnen zu beschönigen. Es wäre sehr praktisch, wenn ich all diese Zahlen mit Kommas formatieren könnte (987654321 wird zu 987.654.321). Es ist komisch, dass in all den vielen Jahren, in denen ich SQL Server verwendet habe, dieses Problem nie aufgetreten ist , da ich die meiste Zeit auf der Präsentationsebene formatiert habe. In diesem Fall ist das T-SQL-Ergebnis in SSMS jedoch die Präsentation.

Ich habe darüber nachgedacht, nur eine einfache CLR-UDF zu erstellen, um dies zu lösen, aber es scheint, dass dies in einfachem alten T-SQL möglich sein sollte. Also werde ich hier die Frage stellen: Wie macht man die numerische Formatierung in Vanilla T-SQL?

mattmc3
quelle
7
Tut "Berichte -> Datenträgernutzung nach Tabelle" das, was Sie benötigen, auf ästhetisch ansprechende Weise?
Martin Smith
1
@ Martin - Wirklich großartig! Ich wusste nicht einmal, dass es das gibt. Ich habe einige meiner DBA-Skripte fast ein Jahrzehnt lang bei mir, also habe ich das völlig verpasst. Trotzdem denke ich, dass diese Frage ein wichtiger Teil der T-SQL-Wissensbasis zum Stackoverflow ist, aber für mein spezifisches Problem ist dies sehr praktisch.
Mattmc3
8
Mit SQL Server 2012 + können Sie die Funktion FORMAT () verwenden. zB '#, ##
Volvox

Antworten:

184

In SQL Server 2012 und höher wird eine Zahl mit Kommas formatiert:

select format([Number], 'N0')

Sie können auch 0die Anzahl der gewünschten Dezimalstellen ändern .

Thomas Müller
quelle
16
Dies ist jetzt die beste Antwort seit Einführung der formatFunktion.
Mattmc3
Es lohnt sich, den dritten (optionalen) Parameter zu beachten culture.
Samuele Colombo
OP spezifiziert SQL Server 2008
Foremaro
254

Während ich allen zustimme, einschließlich des OP, die sagen, dass die Formatierung in der Präsentationsebene erfolgen sollte, kann diese Formatierung in T-SQL durch Casting in moneyund anschließende Konvertierung in erfolgen varchar. Dies schließt jedoch nachfolgende Dezimalstellen ein, mit denen eine Schleife durchgeführt werden könnte SUBSTRING.

SELECT CONVERT(varchar, CAST(987654321 AS money), 1)
Phil Hunt
quelle
12
Obwohl ich der Meinung bin, dass die Formatierung im Allgemeinen an anderer Stelle erfolgen sollte, halten wir alle die Datumsformatierungsfunktionen für selbstverständlich. Das Einfügen von Kommas kann wie hier gezeigt erfolgen. +1.
EBarr
4
Dies funktioniert jedoch nicht für andere Mony-Formatierungsstile. In der Schweiz schreiben wir Geld zum Beispiel in folgender Form: 987'654'321.00 Wie geht das?
Daniel
6
Sie könnten einen SELECT REPLACE ersetzen (CONVERT (varchar, CAST (987654321 AS Geld), 1), ',', '' '')
Hoody
4
Ich bin damit einverstanden, dass die Formatierung nach Möglichkeit in der Präsentationsschicht erfolgen sollte, aber es gibt sicherlich Zeiten, in denen die E-Mail, die ich erhalte, die Präsentationsschicht ist, z. B. bei Ignite / DPA-Warnungen. Die einzige Möglichkeit, Kommas an einer solchen Stelle einzufügen, ist SQL. In diesen Fällen ist es außerordentlich hilfreich, Kommas in großer Anzahl zu haben.
PseudoToad
1
Jeder möchte Ihnen sagen, was "getan" werden soll, aber darum geht es beim Entwerfen Ihres eigenen Codes nicht. Wenn jeder nur das tat, was "getan" werden sollte, verlieren wir den Geist des Erfindungsreichtums und die Fähigkeit, Dinge zusammen zu hacken, um ein Problem schnell und mit minimalem Aufwand zu lösen.
Geoff Griswald
59

Ich würde empfehlen, anstelle von Teilzeichenfolge zu ersetzen, um Probleme mit der Zeichenfolgenlänge zu vermeiden:

REPLACE(CONVERT(varchar(20), (CAST(SUM(table.value) AS money)), 1), '.00', '')
zomf
quelle
3
Auch wenn sich die Geldumwandlung niemals ändern sollte, mag ich die Garantie, nicht die Grenzen zu überschreiten, die Replace gegenüber Substring bietet.
Sean
48

Bei SQL Server 2012+ -Implementierungen können Sie mit FORMAT die Zeichenfolgenformatierung auf Nicht-Zeichenfolgendatentypen anwenden.

In der ursprünglichen Frage hatte der Benutzer die Möglichkeit angefordert, Kommas als Tausendertrennzeichen zu verwenden. In einer als doppelt abgeschlossenen Frage hatte der Benutzer gefragt, wie er die Währungsformatierung anwenden könne. Die folgende Abfrage zeigt, wie beide Aufgaben ausgeführt werden. Es zeigt auch die Anwendung der Kultur, um dies zu einer allgemeineren Lösung zu machen (unter Berücksichtigung der Funktion von Tsiridis Dimitris, griechische Spezialformatierungen anzuwenden).

-- 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 für die oben genannten

billinkc
quelle
1
Toller Anteil, das wird nützlich sein :)
jediCouncilor
1
Geige ist gebrochen, heißt es jetztString index out of range: 33
Jeff Puckett
1
@ JeffPuckettII Ja, es ist schade, dass die Geige für SQL Server nicht mehr funktioniert. Glücklicherweise sollten Sie in der Lage sein, die oben genannten
Informationen
20

Demo 1

Demonstriert das Hinzufügen von Kommas:

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

Demo 2

Zeigt Kommas und Dezimalstellen. Beachten Sie, dass bei Bedarf die letzte Ziffer gerundet wird.

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

Kompatibilität

SQL Server 2012+.

Contango
quelle
2
Das ist der eine! Funktioniert sowohl mit len ​​(Spalte) als auch nur mit Spalte - während eine andere 2012+ Lösung, die ich ausprobiert habe, dies nicht tat.
Graham Laight
1
Toll! Dies ist die Antwort, nach der ich gesucht habe (zur Verwendung mit T-SQL, einschließlich auf SEDE )
ashleedawg
10

Bitte versuchen Sie es mit der folgenden Abfrage:

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

Format mit rechtem Dezimalpunkt:

SELECT FORMAT(987654321,'#,###,##0.###\,###')
Tiến Dũng
quelle
3
Ja, der richtige Weg, jetzt wo wir die FORMATFunktion haben, ist SELECT format(123456789987654321,'###,##0')oder einfacher, select format(123456789987654321, 'N0')wie @ThomasMueller antwortete.
Mattmc3
FORMAT ist ein Performance-Albtraum - Sie beginnen damit und sind darauf angewiesen. Dann stellen Sie fest, dass Ihre Datenbank nicht skaliert werden kann. Und jetzt ist es in ein Dutzend Funktionen integriert, und Sie können sich dem nicht entziehen. Verwenden Sie niemals FORMAT.
Pxtl
9
SELECT REPLACE(CONVERT(varchar(20), (CAST(9876543 AS money)), 1), '.00', '')

Ausgabe = 9.876.543

und Sie können 9876543 durch Ihren Spaltennamen ersetzen.

hojjat.mi
quelle
7

Versuchte den obigen Geldtrick und dies funktioniert hervorragend für numerische Werte mit zwei oder weniger signifikanten Ziffern. Ich habe meine eigene Funktion zum Formatieren von Zahlen mit Dezimalstellen erstellt:

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
havana59er
quelle
4

Dies gehört in einen Kommentar zu Phil Hunts Antwort, aber leider habe ich keinen Repräsentanten.

Um die ".00" am Ende Ihrer Zahlenfolge zu entfernen, ist der Parsename sehr praktisch. Es markiert durch Punkte getrennte Zeichenfolgen und gibt das angegebene Element zurück, beginnend mit dem Token ganz rechts als Element 1.

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

Ausbeuten 987.654.321

Apoxy
quelle
3

Hier ist eine weitere 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
Charles Bretana
quelle
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')`
Tsiridis Dimitris
quelle
1

Hier ist eine Skalarfunktion, die ich verwende und die einige Fehler in einem vorherigen Beispiel (oben) behebt und auch Dezimalwerte (auf die angegebene Anzahl von Ziffern) behandelt (BEARBEITET, um auch mit 0 und negativen Zahlen zu arbeiten). Ein weiterer Hinweis: Die oben beschriebene Methode "Als Geld umwandeln" ist auf die Größe des Datentyps "GELD" beschränkt und funktioniert nicht mit 4 (oder mehr) Dezimalstellen. Diese Methode ist definitiv einfacher, aber weniger flexibel.

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
user2230239
quelle
1

Eine weitere UDF, die hoffentlich allgemein genug ist und keine Annahmen darüber macht, ob Sie auf eine bestimmte Anzahl von Dezimalstellen runden möchten:

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
Mitchell Stiles
quelle
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

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

/ * Diese Funktion benötigt 3 Argumente: Das erste Argument ist @Numero_str, wobei die Zahl als Dateneingabe verwendet wird, und die anderen 2 Argumente geben an, wie die Informationen für die Ausgabe formatiert werden. Diese Argumente sind @Pos_Enteros und @Pos_Decimales, die angeben, wie viele Ganzzahlen und Dezimalstellen, die Sie für die Zahl anzeigen möchten, die Sie als Eingabeargument übergeben. * /

Francisco Cabrera
quelle
0

Erstellen Sie für SQL Server vor 2012, der die FORMAT-Funktion nicht enthält, diese Funktion:

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) gibt 12.345.678,00 USD zurück

Lassen Sie das $ fallen, wenn Sie nur Kommas möchten.

StevenJe
quelle