Sort string as number in sql server

前端 未结 9 1461
不知归路
不知归路 2020-12-20 16:41

I have a column that contains data like this. dashes indicate multi copies of the same invoice and these have to be sorted in ascending order

790711
790109-1         


        
相关标签:
9条回答
  • 2020-12-20 17:22

    Break the sort into two sections:

    SQL Fiddle

    MS SQL Server 2008 Schema Setup:

    CREATE TABLE TestData
    (
      data varchar(20)
    )
    
    INSERT TestData
    SELECT '790711' as data
    UNION
        SELECT '790109-1'
    UNION
        SELECT '790109-11'
    UNION 
        SELECT '790109-2'
    

    Query 1:

    SELECT *
    FROM TestData
    ORDER BY 
        FLOOR(CAST(REPLACE(data, '-', '.') AS FLOAT)),
        CASE WHEN CHARINDEX('-', data) > 0 
            THEN CAST(RIGHT(data, len(data) - CHARINDEX('-', data)) AS INT)
            ELSE 0 
        END
    

    Results:

    |      DATA |
    -------------
    |  790109-1 |
    |  790109-2 |
    | 790109-11 |
    |    790711 |
    
    0 讨论(0)
  • 2020-12-20 17:25

    Try this one -

    Query:

    DECLARE @Invoice TABLE (InvoiceNumber VARCHAR(10))
    INSERT @Invoice 
    VALUES
          ('790711')
        , ('790709-1')
        , ('790709-21')
        , ('790709-11')
        , ('790709-211')
        , ('790709-2')
    
    ;WITH cte AS 
    (
        SELECT 
              InvoiceNumber
            , lenght = LEN(InvoiceNumber)
            , delimeter = CHARINDEX('-', InvoiceNumber)
        FROM @Invoice
    )
    SELECT InvoiceNumber
    FROM cte
    CROSS JOIN (
        SELECT repl = MAX(lenght - delimeter)
        FROM cte
        WHERE delimeter != 0
    ) mx
    ORDER BY 
          SUBSTRING(InvoiceNumber, 1, ISNULL(NULLIF(delimeter - 1, -1), lenght))
        , RIGHT(REPLICATE('0', repl) + SUBSTRING(InvoiceNumber, delimeter + 1, lenght), repl)
    

    Output:

    InvoiceNumber
    -------------
    790709-1
    790709-2
    790709-11
    790709-21
    790709-211
    790711
    
    0 讨论(0)
  • 2020-12-20 17:26

    Try:

    select invoiceid  ... order by Convert(decimal(18, 2), REPLACE(invoiceid, '-', '.'))
    
    0 讨论(0)
  • 2020-12-20 17:29

    My version:

    declare @Len int
    select @Len = (select max (len (invoiceid) -  charindex ( '-', invoiceid))-1 from MyTable)
    
    select 
    invoiceid ,
    cast (SUBSTRING (invoiceid ,1,charindex ( '-', invoiceid )-1) as int) * POWER (10,@Len) + 
    cast (right(invoiceid, len (invoiceid) -  charindex ( '-', invoiceid)  ) as int )
    from MyTable
    

    You can implement this as a new column to your table:

    ALTER TABLE MyTable ADD COLUMN invoice_numeric_id int null
    GO
    
    declare @Len int
    select @Len = (select max (len (invoiceid) -  charindex ( '-', invoiceid))-1 from MyTable)
    
    
    UPDATE TABLE MyTable
    SET  invoice_numeric_id = cast (SUBSTRING (invoiceid ,1,charindex ( '-', invoiceid )-1) as int) * POWER (10,@Len) + 
        cast (right(invoiceid, len (invoiceid) -  charindex ( '-', invoiceid)  ) as int )
    
    0 讨论(0)
  • 2020-12-20 17:33

    Order by each part separately is the simplest and reliable way to go, why look for other approaches? Take a look at this simple query.

    select *
    from Invoice
    order by Convert(int, SUBSTRING(invoiceid, 0, CHARINDEX('-',invoiceid+'-'))) asc,
             Convert(int, SUBSTRING(invoiceid, CHARINDEX('-',invoiceid)+1, LEN(invoiceid)-CHARINDEX('-',invoiceid))) asc
    
    0 讨论(0)
  • 2020-12-20 17:36

    Try this

    SELECT invoiceid FROM Invoice
    ORDER BY 
    CASE WHEN PatIndex('%[-]%',invoiceid) > 0
          THEN LEFT(invoiceid,PatIndex('%[-]%',invoiceid)-1)
          ELSE invoiceid END * 1
    ,CASE WHEN PatIndex('%[-]%',REVERSE(invoiceid)) > 0
          THEN RIGHT(invoiceid,PatIndex('%[-]%',REVERSE(invoiceid))-1)
          ELSE NULL END * 1
    

    SQLFiddle Demo

    Above query uses two case statements

    1. Sorts first part of Invoiceid 790109-1 (eg: 790709)
    2. Sorts second part of Invoiceid after splitting with '-' 790109-1 (eg: 1)

    For detailed understanding check the below SQLfiddle

    SQLFiddle Detailed Demo

    OR use 'CHARINDEX'

    SELECT invoiceid FROM Invoice
    ORDER BY 
    CASE WHEN CHARINDEX('-', invoiceid) > 0
          THEN LEFT(invoiceid, CHARINDEX('-', invoiceid)-1)
          ELSE invoiceid END * 1
    ,CASE WHEN CHARINDEX('-', REVERSE(invoiceid)) > 0
          THEN RIGHT(invoiceid, CHARINDEX('-', REVERSE(invoiceid))-1)
          ELSE NULL END * 1
    
    0 讨论(0)
提交回复
热议问题