ฉันจะจัดรูปแบบตัวเลขด้วยเครื่องหมายจุลภาคใน T-SQL ได้อย่างไร


202

ฉันใช้คำสั่งการบริหารและรวบรวมผลจากsp_spaceusedใน SQL Server 2008 เพื่อดูอัตราส่วนพื้นที่ข้อมูล / ดัชนีของบางตารางในฐานข้อมูลของฉัน แน่นอนฉันได้รับจำนวนมากในผลลัพธ์และตาของฉันเริ่มแวววาว มันจะสะดวกมากถ้าฉันสามารถจัดรูปแบบตัวเลขเหล่านั้นด้วยเครื่องหมายจุลภาค (987654321 กลายเป็น 987,654,321) ขำ ๆ ที่หลายปีที่ผ่านมาฉันเคยใช้ SQL Server ปัญหานี้ไม่เคยเกิดขึ้นเพราะส่วนใหญ่ฉันจะทำการฟอร์แมตที่เลเยอร์การนำเสนอ แต่ในกรณีนี้ผลลัพธ์ T-SQL ใน SSMS เป็นการนำเสนอ

ฉันได้พิจารณาว่าจะสร้าง CLF UDF อย่างง่ายเพื่อแก้ปัญหานี้ แต่ดูเหมือนว่าสิ่งนี้ควรจะสามารถทำได้ใน T-SQL แบบเก่าธรรมดา ดังนั้นฉันจะถามคำถามที่นี่ - คุณจะจัดรูปแบบตัวเลขในวานิลลา T-SQL ได้อย่างไร


7
"Reports -> Disk Usage by Table" ทำในสิ่งที่คุณต้องการในแบบที่น่าพอใจหรือไม่
Martin Smith

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พารามิเตอร์
Samuele Colombo

OP ระบุ SQL Server 2008
foremaro

254

ในขณะที่ผมเห็นด้วยกับทุกคนรวมทั้ง OP ที่กล่าวว่าการจัดรูปแบบควรจะทำในชั้นนำเสนอการจัดรูปแบบนี้สามารถทำได้ใน T-SQL โดยการหล่อไปแล้วแปลงไปmoney varcharนี้ไม่รวมถึงทศนิยมต่อท้าย SUBSTRINGแต่ที่อาจจะคล้องออกด้วย

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

12
ในขณะที่ฉันยอมรับว่าการจัดรูปแบบโดยทั่วไปควรเกิดขึ้นที่อื่นเราทุกคนใช้ฟังก์ชั่นการจัดรูปแบบวันที่เพื่อรับสิทธิ์ การใส่เครื่องหมายจุลภาคสามารถทำได้ดังแสดงที่นี่ +1
EBarr

4
อย่างไรก็ตามวิธีนี้ใช้ไม่ได้กับรูปแบบการจัดรูปแบบอื่น ๆ ในประเทศสวิตเซอร์แลนด์เราเขียนเงินสำหรับตัวอย่างในรูปแบบนี้: 987'654'321.00 ทำอย่างไร?
แดเนียล

6
คุณสามารถทำการแทนที่ SELECT REPLACE (แปลง (varchar, CAST (987654321 เป็นเงิน), 1), ',', ',' '' ')
Hoody

4
แม้ว่าฉันยอมรับว่าการจัดรูปแบบควรทำในเลเยอร์การนำเสนอเท่าที่เป็นไปได้ แต่ก็มีบางครั้งเช่นด้วยการแจ้งเตือน Ignite / DPA ว่าอีเมลที่ฉันได้รับเป็นเลเยอร์การนำเสนอ วิธีเดียวที่จะใส่เครื่องหมายจุลภาคในสถานที่เช่นที่ผ่าน SQL การมีเครื่องหมายจุลภาคเป็นจำนวนมากจะเป็นประโยชน์อย่างมากในกรณีเหล่านั้น
PseudoToad

1
ทุกคนต้องการบอกคุณว่า "ควร" ทำอะไร แต่นั่นไม่ใช่สิ่งที่ออกแบบรหัสของคุณเอง หากทุกคนทำในสิ่งที่ "ควรทำ" เราจะสูญเสียจิตวิญญาณแห่งความคิดสร้างสรรค์และความสามารถในการแฮ็กสิ่งต่าง ๆ เข้าด้วยกันเพื่อแก้ไขปัญหาอย่างรวดเร็วด้วยความยุ่งยากและความพยายามน้อยที่สุด
Geoff Griswald

59

ฉันขอแนะนำแทนที่แทนที่ Substring เพื่อหลีกเลี่ยงปัญหาความยาวสตริง:

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

3
แม้ว่าการแปลงเงินไม่ควรเปลี่ยนแปลง แต่ฉันชอบการรับประกันว่าจะไม่ออกนอกขอบเขตที่แทนที่ข้อเสนอผ่าน Substring
Sean

48

สำหรับการปรับใช้ SQL Server 2012+ คุณจะมีความสามารถในการใช้รูปแบบเพื่อใช้การจัดรูปแบบสตริงกับชนิดข้อมูลที่ไม่ใช่สตริง

ในคำถามเดิมผู้ใช้ร้องขอความสามารถในการใช้เครื่องหมายจุลภาคเป็นตัวคั่นหลักพัน ในคำถามที่ปิดเป็นคำถามซ้ำผู้ใช้ถามว่าพวกเขาสามารถใช้การจัดรูปแบบสกุลเงินได้อย่างไร แบบสอบถามต่อไปนี้แสดงวิธีการทำงานทั้งสองอย่าง นอกจากนี้ยังแสดงให้เห็นถึงการประยุกต์ใช้วัฒนธรรมเพื่อทำให้สิ่งนี้เป็นคำตอบที่กว้างกว่าเดิม (กล่าวถึงหน้าที่ของ Tsiridis Dimitris เพื่อใช้การจัดรูปแบบพิเศษของกรีก)

-- 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
ซอเสียตอนนี้พูดว่าString index out of range: 33
Jeff Puckett

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+ อีกอันที่ฉันพยายามทำไม่ได้
Graham Laight

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 เป็นฝันร้ายของการแสดง - คุณเริ่มใช้มันและขึ้นอยู่กับมันแล้วพบว่าฐานข้อมูลของคุณไม่สามารถขยายขนาดได้ และตอนนี้มันถูกสร้างขึ้นด้วยคุณสมบัติโหลและคุณไม่สามารถหลบหนีได้ อย่าใช้รูปแบบ
Pxtl

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

เอาต์พุต = 9,876,543

และคุณสามารถแทนที่ 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

นี่เป็นความคิดเห็นของPhil Huntมีต่อคำตอบของแต่ทว่าฉันไม่มีตัวแทน

หากต้องการตัด ".00" ออกจากจุดสิ้นสุดของสตริงตัวเลขของคุณ parsename จะสะดวกมาก มัน tokenizes สตริงที่คั่นด้วยระยะเวลาและส่งกลับองค์ประกอบที่ระบุเริ่มต้นด้วยโทเค็นขวาสุดเป็นองค์ประกอบ 1

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

ผลตอบแทน "987,654,321"


3

นี่คือ 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

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 ซึ่ง Number เป็นอินพุตข้อมูลและอีก 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 รูปแบบสกุลเงิน (12345678) ส่งคืน $ 12,345,678.00

วาง $ ถ้าคุณต้องการคอมม่า

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.