Как отсортировать столбец, состоящий из букв и цифр

#sql #sql-server #tsql

Вопрос:

У меня есть таблица SQL Server, содержащая столбец, содержащий значения, состоящие из букв и цифр, таких как «u-340″,»u42/43″,»u-44″,»u-540», и он отображается в этом порядке, когда я делаю запрос select по его имени.

Когда мой запрос Select Name from table1 order by Name , он отображается в следующем порядке

  1. u-340
  2. u42/43
  3. u-44
  4. u-540

Как я могу сделать так, чтобы это выглядело так

  1. u42/43
  2. u-44
  3. u-340
  4. u-540

Комментарии:

1. С трудом. Если вы хотите, чтобы значения обрабатывались как числа, они должны быть в другом столбце, в строго типизированном числовом типе данных

2. Предположим, что данные были { 'u-1', 'u-2/u-4', 'u-3' } . Как бы вы хотели, чтобы это рассортировалось?

3. это будет не так, но всегда число после знака «/» является следующим числом. таким образом, это будет {«u-1», «u-2/u-3», «u-4» }

Ответ №1:

Вот один из способов. Я замечаю , что иногда ваши данные начинаются с swith u- , а в других случаях они начинаются с just u . Похоже, что это сделано намеренно, потому что у вас это есть в вашем вопросе дважды, поэтому этот ответ предполагает, что это так. Если это не так, то дайте мне знать, и ответ можно упростить.

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

Я также не знаю, насколько большими могут быть ваши числа, поэтому для целей этого ответа я допустил до 8-значных чисел.

 select      table1.*
from        table1
cross apply (select cast(replace(replace(name, 'u', ''), '/', '.') as decimal(16,8))) t(v)
order by    t.v * sign(t.v)
 

Или с abs (быстрее, чем sign ? Возможно)

 select      *
from        t
order by    abs(cast(replace(replace(name, 'u', ''), '/', '.') as decimal(16,8)))
 

Комментарии:

1. но только одна проблема возникает, когда я пытаюсь сделать это с другой таблицей, которая имеет те же значения, что и упомянутые выше, плюс строки без цифр! затем у меня возникла ошибка неудачного преобразования типа данных nvarchar в числовой. Поэтому для упрощения, если мы предположим, что данные {«u-340″,»u42/43″,»u-44″,»u-540″,»привет»,»Коричневый»}. затем я получаю неудачное преобразование ошибки из nvarchar в числовое

Ответ №2:

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

Если это так, вам просто нужно извлечь это и использовать в качестве критерия заказа.

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

 select name
from table1 t
cross apply (values(Stuff(name,1,PatIndex('%[0-9]%',name)-1,'')))s(v)
order by Try_Cast(Left(v,IsNull(NullIf(PatIndex('%[^0-9]%',v)-1,-1),10)) as int)
 

Комментарии:

1. Это тоже сработало идеально, сэр, большое вам спасибо

2. но только одна проблема возникает, когда используется «distinct», это дает мне эту ошибку: «ПОРЯДОК ПО элементам должен отображаться в списке выбора, если указан параметр ВЫБРАТЬ DISTINCT». у вас есть какие-либо идеи, пожалуйста, почему это происходит