Сортировка символов по возрастанию, а затем по возрастанию - PullRequest
1 голос
/ 11 апреля 2019

Есть ли простой способ изменить порядок сортировки на «сначала по возрастанию значения символов, затем по возрастанию числовых значений»

   SELECT mycol
     FROM mytable
 ORDER BY mycol

Результат:

1C
8Q
9G
AR
BZ
IT

С DESC:

   SELECT mycol
     FROM mytable
 ORDER BY mycol DESC

Результат:

IT
BZ
AR
9G
8Q
1C

Желаемый результат:

AR
BZ
IT
1C
8Q
9G

Ответы [ 6 ]

2 голосов
/ 11 апреля 2019

Просто, просто:

SELECT *
FROM (VALUES 
    ('1C'),
    ('8Q'),
    ('9G'),
    ('AR'),
    ('BZ'),
    ('IT'),
    ('11'),
    ('2A')
) AS tbl(col)
ORDER BY CASE WHEN col LIKE '[0-9]%' THEN 2 ELSE 1 END
       , col

Выход:

AR
BZ
IT
11
1C
2A
8Q
9G
2 голосов
/ 11 апреля 2019

Эта опция разделит столбец на 2, чтобы разделить цифры и буквы.

SELECT *
FROM (VALUES('1C'),('8Q'),('9G'),('AR'),('BZ'),('IT'))x(MyCol)
ORDER BY SUBSTRING(MyCol, 0, PATINDEX( '%[A-Z]%', MyCol)),
         SUBSTRING(MyCol, PATINDEX( '%[A-Z]%', MyCol), 10);
2 голосов
/ 11 апреля 2019

Здесь можно попробовать использовать функцию ASCII вместе с выражением CASE:

SELECT mycol
FROM mytable
ORDER BY
    CASE WHEN LEFT(mycol, 1) LIKE '[A-Z]' THEN 0 ELSE 1 END,
    LEFT(mycol, 1),
    CASE WHEN RIGHT(mycol, 1) LIKE '[A-Z]' THEN 0 ELSE 1 END,
    RIGHT(mycol, 1);

enter image description here

Демо

Логика здесь использует четыре уровня сортировки, пару для каждого из двух символов в mycol. Выражения CASE ставят буквы перед цифрами. После этого мы просто сортируем по возрастанию по номеру или букве.

Еще один подход к этому состоит в том, чтобы рассматривать ваш столбец как основную цифру 36 (10 цифр плюс 26 букв), а затем просто сортировать на основе этого числа, преобразованного обратно в десятичную основную цифру 10. Но это может быть уродливее и запутаннее, чем решение, которое я выложил выше.

0 голосов
/ 15 апреля 2019

Еще одним решением, которое я нашел, было бы использование COLLATE для предложения ORDER BY, используя сопоставление EBCDIC. Производительность так же быстро, как и другие решения. Может быть, легче написать, но как-то сложно читать без комментариев. Преимущество заключается в том, что он работает и для столбцов, содержащих более 1 или 2 символов.

SELECT mycol
     FROM mytable
 ORDER BY mycol COLLATE SQL_EBCDIC278_CP1_CS_AS
0 голосов
/ 11 апреля 2019

Мой вариант ответов @ TimBiegeleisen и @ SalmanA:

SELECT mycol
FROM mytable
ORDER BY
    CASE WHEN mycol LIKE '[^0-9]%' THEN 0 ELSE 1 END,
    mycol;

(Я не знаю, могут ли индексы по столбцам в предложении ORDER BY влиять на производительность, но, чтобы быть уверенным, я бы избегал вызовов функций.)

Редактировать: Ну, на самом деле это практически тот же ответ, что и у @ SalmanA ...

0 голосов
/ 11 апреля 2019

Попробуйте это:

DECLARE @mytable TABLE
( MyCol VARCHAR(3))

insert @mytable VALUES ('IT'),('BZ'),('AR'),('1C'),('8Q')

SELECT
     MyCol
FROM @mytable
ORDER BY PATINDEX('[0-9]%',MyCol),MyCol
...