Sorting multiple types of numbers and characters

你离开我真会死。 提交于 2020-01-16 04:00:28

问题


How to sort a table with different numbers and characters. Column in my table is

res_no
------
B14                         
A6                              
C16
105 FF
114A
113
37
39A
91G
93
93(2)
A143B
A141
D154a
A141(25)
C40FF
D153(1)
E18A
D154
A51A
A50
E18A1 

   

I want to sort this like

res_no
------

37  
39A  
91G 
93 
93(2)  
105FF 
113
114A
A6
A50
A51A
A141
A141(25)
A143B
B14
C40FF
D153(1)
D154
D154A
E18A
E18A1 

I tried to ORDER BY:

REGEXP ('^[0-9]')
CAST(res_no AS UNSIGNED)
REGEXP_SUBSTR(res_no, '(^[a-zA-Z]+)|([a-zA-Z]$)')
CAST(REGEXP_SUBSTR(res_no, '(^[0-9]+)|([0-9]+$)') AS UNSIGNED

How to solve this? Sorting numbers, alphanumerical values is working perfect with above code but values inside parentheses and like A50,A51A are not sorting correctly.


回答1:


This query should give you the results you want. The query orders on 5 things:

  1. A starting set of letters (if not present, this will be empty and so values starting with numbers will sort before those starting with letters);
  2. The first number in the string (which may be preceded by letters);
  3. The second set of letters in the string (if present);
  4. A trailing number enclosed in parentheses (if present);
  5. A trailing number not enclosed in parentheses (if present).
SELECT res_no
FROM table1
ORDER BY REGEXP_SUBSTR(res_no, '^[a-zA-Z]+'),
         CAST(REGEXP_REPLACE(res_no, '^[a-zA-Z]*([0-9]+)', '\\1') AS UNSIGNED),
         REGEXP_SUBSTR(res_no, '(?<=[0-9])[a-zA-Z]+'),
         CAST(REGEXP_SUBSTR(res_no, '(?<=\\()[0-9]+(?=\\))') AS UNSIGNED),
         CAST(REGEXP_SUBSTR(res_no, '[0-9]+$') AS UNSIGNED)

Output:

res_no
37
39A
91G
93
93(2)
105FF
113
114A
A6
A50
A51A
A141
A141(25)
A143B
B14
C16
C40FF
D153(1)
D154
D154a
E18A
E18A1

Demo on dbfiddle




回答2:


For the sample data that you posted this will work:

select * from tablename
order by 
  res_no + 0 > 0 desc,
  res_no + 0,
  left(res_no, 1),
  substr(res_no, 2) + 0,
  case 
    when res_no like '%(%)%' then
      substring_index(substring_index(res_no, ')', 1), '(', -1) + 0
    else ''
  end,
  length(res_no),
  reverse(reverse(res_no) + 0) + 0,
  right(res_no, 1)

See the demo.
Results:

| res_no   |
| -------- |
| 37       |
| 39A      |
| 91G      |
| 93       |
| 93(2)    |
| 105 FF   |
| 113      |
| 114A     |
| A6       |
| A50      |
| A51A     |
| A141     |
| A141(25) |
| A143B    |
| B14      |
| C16      |
| C40FF    |
| D153(1)  |
| D154     |
| D154a    |
| E18A     |
| E18A1    |



回答3:


This is quite tricky for me however I'm able to get your desired result with this query. Might not be the solution but hopefully you'll get ideas from it.

My approach is to:

  1. Extract the numbers out from the res_no value. I'm using REGEXP_REPLACE to find any alphabetic value in res_no and replace with empty value. So the output is just (CAST AS UNSIGNED) numbers.
   CAST(REGEXP_REPLACE(res_no,' *[A-Z] *', '') AS UNSIGNED) AS numbers
  1. Assign custom row number value by numbers as 1, A as 2, B as 3.. and so forth. So if your res_no value spans until Z, well..
   CASE WHEN res_no REGEXP ('^[0-9]')=1 THEN 1 
                   WHEN res_no LIKE 'A%' THEN 2
                   WHEN res_no LIKE 'B%' THEN 3
                   WHEN res_no LIKE 'C%' THEN 4
                   WHEN res_no LIKE 'D%' THEN 5
                   WHEN res_no LIKE 'E%' THEN 6
                   WHEN res_no LIKE 'F%' THEN 7 END AS rownum 
  1. The last part is to do the ordering based on rownum first then numbers and I added a last condition LENGTH(res_no) because I was getting some ordering like the 93, 93(2) the other way around.
  SELECT res_no,
         CAST(REGEXP_REPLACE(res_no,' *[A-Z] *', '') AS UNSIGNED) AS numbers,
         CASE WHEN res_no REGEXP ('^[0-9]')=1 THEN 1 
              WHEN res_no LIKE 'A%' THEN 2
              WHEN res_no LIKE 'B%' THEN 3
              WHEN res_no LIKE 'C%' THEN 4
              WHEN res_no LIKE 'D%' THEN 5
              WHEN res_no LIKE 'E%' THEN 6
              WHEN res_no LIKE 'F%' THEN 7 END AS rownum 
    FROM TableA     
ORDER BY rownum,numbers,LENGTH(res_no);

The query above generated the following output:

+----------+---------+--------+
|  res_no  | numbers | rownum |
+----------+---------+--------+
| 37       |      37 |      1 |
| 39A      |      39 |      1 |
| 91G      |      91 |      1 |
| 93       |      93 |      1 |
| 93(2)    |      93 |      1 |
| 105FF    |     105 |      1 |
| 113      |     113 |      1 |
| 114A     |     114 |      1 |
| A6       |       6 |      2 |
| A50      |      50 |      2 |
| A51A     |      51 |      2 |
| A141     |     141 |      2 |
| A141(25) |     141 |      2 |
| A143B    |     143 |      2 |
| B14      |      14 |      3 |
| C40FF    |      40 |      4 |
| D153(1)  |     153 |      5 |
| D154     |     154 |      5 |
| D154A    |     154 |      5 |
+----------+---------+--------+

Now, you make the query like below and also get the same result:

SELECT res_no 
  FROM TableA
ORDER BY CASE WHEN res_no REGEXP ('^[0-9]')=1 THEN 1 
              WHEN res_no LIKE 'A%' THEN 2
              WHEN res_no LIKE 'B%' THEN 3
              WHEN res_no LIKE 'C%' THEN 4
              WHEN res_no LIKE 'D%' THEN 5
              WHEN res_no LIKE 'E%' THEN 6
              WHEN res_no LIKE 'F%' THEN 7 END,
         CAST(REGEXP_REPLACE(res_no,' *[A-Z] *', '') AS UNSIGNED),
         LENGTH(res_no);

Switching from SELECT to ORDER BY. Btw I'm using MariaDB 10.3;




回答4:


If I understand correctly, you want leading digits first by number and the rest alphabetically following.

The following query does this:

select t.*
from t
order by (res_no + 0) > 0 desc,  -- numbers first
         (res_no + 0),
         res_no;

Here is a db<>fiddle.

You can "special case" the a records:

select t.*
from t
order by (res_no + 0) > 0 desc,  -- numbers first
         (res_no + 0),
         (case when res_no like 'A%' then res_no end) desc,
         res_no;


来源:https://stackoverflow.com/questions/58023005/sorting-multiple-types-of-numbers-and-characters

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!