#sql #sql-server #tsql
Вопрос:
У меня есть таблица SQL Server, содержащая столбец, содержащий значения, состоящие из букв и цифр, таких как «u-340″,»u42/43″,»u-44″,»u-540», и он отображается в этом порядке, когда я делаю запрос select по его имени.
Когда мой запрос Select Name from table1 order by Name
, он отображается в следующем порядке
- u-340
- u42/43
- u-44
- u-540
Как я могу сделать так, чтобы это выглядело так
- u42/43
- u-44
- u-340
- 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». у вас есть какие-либо идеи, пожалуйста, почему это происходит