Як відформатувати число комами в T-SQL?


202

Я виконую кілька адміністративних запитів і збираю результати з sp_spaceusedSQL Server 2008, щоб переглянути співвідношення простору даних / індексів деяких таблиць у моїй базі даних. Звичайно, я отримую всіляку велику кількість результатів, і мої очі починають блищати. Було б дуже зручно, якби я зміг відформатувати всі ці числа комами (987654321 стає 987 654 321). Смішно, що за всі багато років, якими я користувався SQL Server, ця проблема ніколи не виникала, оскільки більшість часу я б робив форматування на презентаційному шарі, але в цьому випадку результатом T-SQL в SSMS є презентація.

Я вирішив просто створити простий URF CLR для вирішення цього питання, але, здається, це має бути спроможним у простому старому T-SQL. Отже, я поставлю тут питання - як ви робите числове форматування у ванільному T-SQL?


7
Чи "Звіти -> Використання диска за таблицею" роблять те, що вам потрібно в естетичному плані?
Мартін Сміт

1
@Martin - Воістину приголомшливий! Навіть не знали, що існує. Я носив із собою кілька моїх сценаріїв DBA протягом майже десятиліття, тому я цілком пропустив це. Але я вважаю, що це питання є важливою частиною бази знань T-SQL про stackoverflow, але для моєї конкретної проблеми це дуже зручно.
mattmc3

8
За допомогою SQL Server 2012 + Ви можете використовувати функцію FORMAT (). напр. "#, ##. 000" msdn.microsoft.com/en-us/library/hh213505.aspx
Volvox

Відповіді:


188

У SQL Server 2012 і новіших версіях це буде форматувати число комами:

select format([Number], 'N0')

Ви також можете змінити 0кількість потрібних знаків після коми.


16
Зараз це найкраща відповідь з моменту введення formatфункції.
mattmc3

варто помітити третій (необов’язковий) параметр culture.
Самуеле Коломбо

OP вказав SQL Server 2008
foremaro

254

Хоча я погоджуюся з усіма, включаючи ОП, хто каже, що форматування слід проводити в презентаційному шарі, це форматування може бути виконане в T-SQL шляхом передачі moneyта перетворення в varchar. Сюди ж входять десяткові знаки, які можуть бути відключені SUBSTRING.

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

12
Хоча я погоджуюся, що загалом форматування має відбуватися в іншому місці, ми всі приймаємо функції форматування дати як належне. Вставлення комок можна зробити, як показано тут. +1.
EBarr

4
Однак це не працює для інших стилів форматування моні. Наприклад, у Швейцарії ми пишемо гроші у такій формі: 987'654'321.00 Як це зробити?
Даніель

6
Ви можете зробити заміну ВИБІР ЗАМІНИ (CONVERT (varchar, CAST (987654321 AS гроші), 1), ',', '' '')
Hoody

4
Хоча я погоджуюся, що форматування слід проводити в презентаційному шарі, де це можливо, але, звичайно, є випадки, наприклад, з попередженнями Ignite / DPA, що електронний лист, який я отримую, є презентаційним шаром. Єдиний спосіб помістити коми в таке місце, як це через SQL. Велика кількість комами в цих випадках надзвичайно корисна.
PseudoToad

1
Усі хочуть сказати вам, що слід робити, але це не те, що стосується розробки власного коду. Якби кожен робив лише те, що слід «зробити», тоді ми втрачаємо той дух винахідливості та здатність разом зламати речі, щоб швидко вирішити проблему з мінімальною суєтою та зусиллями.
Джефф Грісвальд

59

Я рекомендую замінити замість підрядкових рядків, щоб уникнути проблем із довжиною рядків:

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

3
Незважаючи на те, що конвертація грошей ніколи не повинна змінюватися, мені подобається гарантія не виходити за межі, які пропонує Замінити пропозиції на підрядку.
Шон

48

Для реалізацій SQL Server 2012+ ви матимете можливість використовувати FORMAT для застосування форматування рядків до нерядкових типів даних.

У оригінальному запитанні користувач попросив можливість використовувати коми як тисячі роздільників. У закритому, як повторюваному запитанні користувач запитав, як вони можуть застосовувати форматування валюти. Наступний запит показує, як виконати обидва завдання. Він також демонструє застосування культури, щоб зробити це більш загальним рішенням (звертаючись до функції Цирідіс Димитріса щодо застосування грецького спеціального форматування)

-- 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
Чудова частка, це стане у нагоді :)
jediCouncilor

1
Fiddle зламана, тепер сказаноString index out of range: 33
Джефф Пукетт

1
@JeffPuckettII Так, шкода, що загадка для SQL Server більше не працює. На щастя, ви зможете вставити вищезазначене в будь-який інструмент запитів, підключений до SQL Server 2012+
billinkc

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 (колонка), а також просто стовпцем - тоді як іншого 2012+ рішення, яке я спробував, не зробив.
Грем Лайт

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

FORMAT - це кошмар від продуктивності - ви починаєте використовувати його і залежати від нього, а потім виявите, що ваша база даних не може нарощувати масштаб. А тепер він вбудований у десяток функцій, і вам не обійти його. Ніколи не використовуйте FORMAT.
Pxtl

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

вихід = 9 876 533

і ви можете замінити 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

Це належить до коментаря до відповіді Філа Ханта , але, на жаль, у мене немає представника.

Щоб зняти ".00" з кінця рядка номера, синтаксичний синтаксис дуже зручний. Він токенізує рядки, обмежені періодом, і повертає вказаний елемент, починаючи з правого правого маркера як елемента 1.

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

Врожайність "987 654 321"


3

ось ще один 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

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, який вводить число як дані, а інші 2 аргументи визначають, як буде форматизована інформація для виводу; ці аргументи є @Pos_Enteros та @Pos_Decimales, які визначають, скільки Цілі числа і десяткові місця, які ви хочете показати для числа, яке ви передаєте як аргумент введення. * /


0

Для SQL Server до 2012 року, який не включає функцію FORMAT, створіть цю функцію:

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) повертає $ 12 345 678,00

Відкиньте $, якщо ви просто хочете комами.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.