Сортировка нескольких типов чисел и символов - PullRequest
1 голос
/ 20 сентября 2019

Как отсортировать таблицу с разными цифрами и символами.Столбец в моей таблице

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 

   

Я хочу отсортировать это как

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 

Я пытался 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

Как это решить?Сортировка чисел, буквенно-цифровых значений прекрасно работает с приведенным выше кодом, но значения в скобках и, например, A50, A51A сортируют неправильно.

Ответы [ 4 ]

2 голосов
/ 21 сентября 2019

Этот запрос должен дать вам результаты, которые вы хотите.Запрос состоит из 5 элементов:

  1. Начальный набор букв (если его нет, он будет пустым, поэтому значения, начинающиеся с цифр, будут сортироваться перед значениями, начинающимися с букв);
  2. Первое число в строке (которому могут предшествовать буквы);
  3. второй набор букв в строке (если имеется);
  4. конечный номер, заключенный в скобки (если есть));
  5. Завершающий номер, не заключенный в скобки (если есть).
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)

Вывод:

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

Демонстрация на dbfiddle

2 голосов
/ 20 сентября 2019

Для примеров данных, которые вы разместили, это будет работать:

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)

См. Демоверсию .Результаты:

| 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    |
1 голос
/ 20 сентября 2019

Если я правильно понимаю, вы хотите, чтобы первые цифры начинались с номера, а остальные в алфавитном порядке.

Следующий запрос делает это:

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

Здесь - этоdb <> скрипка.

Вы можете "особый случай" для записей a:

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;
1 голос
/ 20 сентября 2019

Это довольно сложно для меня, однако я могу получить желаемый результат с помощью этого запроса.Может не быть решением, но, надеюсь, вы получите идеи из него.

Мой подход заключается в следующем:

  1. Извлечение чисел из значения res_no.Я использую REGEXP_REPLACE, чтобы найти любое буквенное значение в res_no и заменить его пустым значением.Таким образом, на выходе просто (CAST AS UNSIGNED) числа.
   CAST(REGEXP_REPLACE(res_no,' *[A-Z] *', '') AS UNSIGNED) AS numbers
Назначить пользовательское значение номера строки по номерам как 1, A как 2, B как 3 ... и так далее.Так что, если ваше res_no значение простирается до Z, хорошо ..
   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 
Последняя часть состоит в том, чтобы сначала упорядочить на основе rownum, а затем чисел, и я добавил последнее условие LENGTH(res_no), потому что я получал некоторое упорядочение, например 93, 93(2), наоборот.
  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);

Приведенный выше запрос сгенерировал следующий вывод:

+----------+---------+--------+
|  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 |
+----------+---------+--------+

Теперь вы выполняете запрос, как показано ниже, и также получаете тот же результат:

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);

Переключение с SELECTдо ORDER BY.Кстати, я использую MariaDB 10,3;

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...