Postgresql sorting mixed alphanumeric data

前端 未结 7 1456
无人及你
无人及你 2020-12-30 05:32

Running this query:

select name from folders order by name

returns these results:

alphanumeric
a test
test 20
test 19
test          


        
相关标签:
7条回答
  • 2020-12-30 06:12

    You can simply cast name column to bytea data type allowing collate-agnostic ordering:

    SELECT name
    FROM folders
    ORDER BY name::bytea;
    

    Result:

         name     
    --------------
     a test
     alphanumeric
     test 1
     test 10
     test 19
     test 20
    (6 rows)
    
    0 讨论(0)
  • 2020-12-30 06:17
    select * from "public"."directory" where "directoryId" = 17888 order by
    COALESCE(SUBSTRING("name" FROM '^(\d+)')::INTEGER, 99999999),
    SUBSTRING("name" FROM '[a-zA-z_-]+'),
    COALESCE(SUBSTRING("name" FROM '(\d+)$')::INTEGER, 0),
    "name";
    

    NOTE: Escape the regex as you need, in some languages, you will have to add one more "\".

    In my Postgres DB, name column contains following, when I use simple order by name query:

    • 1
    • 10
    • 2
    • 21
    • A
    • A1
    • A11
    • A5
    • B
    • B2
    • B22
    • B3
    • M 1
    • M 11
    • M 2

    Result of Query, After I have modified it:

    • 1
    • 2
    • 10
    • 21
    • A
    • A1
    • A5
    • A11
    • B
    • B2
    • B3
    • B22
    • M 1
    • M 2
    • M 11
    0 讨论(0)
  • 2020-12-30 06:18

    You may be able to manually sort by splitting the text up in case there is trailing numerals, like so:

    SELECT * FROM sort_test
    ORDER BY SUBSTRING(text FROM '^(.*?)( \\d+)?$'),
             COALESCE(SUBSTRING(text FROM ' (\\d+)$')::INTEGER, 0);
    

    This will sort on column text, first by all characters optionally excluding an ending space followed by digits, then by those optional digits.

    Worked well in my test.

    Update fixed the string-only sorting with a simple coalesce (duh).

    0 讨论(0)
  • 2020-12-30 06:20

    All of this methods sorted my selection in alphabetical order:

    test 1
    test 10
    test 2
    test 20
    

    This solution worked for me (lc_collate: 'ru_RU.UTF8'):

    SELECT name
    FROM folders
    ORDER BY SUBSTRING(name FROM '([0-9]+)')::BIGINT ASC, name;
    
    test 1
    test 2
    test 10
    test 20
    
    0 讨论(0)
  • 2020-12-30 06:20

    OverZealous answer helped me but didn't work if the string in the database begun with numbers followed by additional characters.

    The following worked for me:

    SELECT name
    FROM folders
    ORDER BY
    COALESCE(SUBSTRING(name FROM '^(\\d+)')::INTEGER, 99999999),
    SUBSTRING(name FROM '^\\d* *(.*?)( \\d+)?$'),
    COALESCE(SUBSTRING(name FROM ' (\\d+)$')::INTEGER, 0),
    name;
    

    So this one:

    1. Extracts the first number in the string, or uses 99999999.
    2. Extracts the string that follows the possible first number.
    3. Extracts a trailing number, or uses 0.
    0 讨论(0)
  • 2020-12-30 06:22

    A Vlk's answer above helped me a lot, but it sorted items only by the numeric part, which in my case came second. My data was like (desk 1, desk 2, desk 3 ...) a string part, a space and a numeric part. The syntax in A Vlk's answer returned the data sorted by the number, and at that it was the only answer from the above that did the trick. However when the string part was different, (eg desk 3, desk 4, table 1, desk 5...) table 1 would get first from desk 2. I fixed this using the syntax below:

        ...order by SUBSTRING(name,'\\w+'), SUBSTRINGname FROM '([0-9]+)')::BIGINT ASC;
    
    0 讨论(0)
提交回复
热议问题