T-Sql — Заказ по буквенно-цифровому

у меня есть список буквенно-цифровых токенов, скажем, '1a', '1b', '02', '03', '10', '11', и т.д...

Итак, как лучше всего сделать заказ по этому списку токенов?

Я получаю '1a', '1b', '10', '11', '02', '03',

но мне нужно, чтобы это было

'1a', '1b', '02', '03', '10', '11' 

ОБНОВЛЕНИЕ

хорошо, я делаю это после предложения, но это не работает.

declare @tokens table(token varchar(20));

insert into @tokens
select '1a'
select '1b'
select '02'
select '10'

select * from @tokens
order by case
 when ISNUMERIC(token) = 1 then right('0000000000'+token+'0',10)
 else right('0000000000'+token,10)
 end

Я получаю ответ как '1b', '02', '10', '1a'

ОБНОВЛЕНИЕ 2

Это работает после внесения следующего изменения.

declare @tokens table(token varchar(20));

insert into @tokens
select '1a'
insert into @tokens
select '1b'
insert into @tokens
select '02'
insert into @tokens
select '10'


select token from @tokens
order by case
 when ISNUMERIC(token) = 1 then right('0000000000'+token+'0',10)
 else right('0000000000'+token,10)
 end

Спасибо всем вам за ваши хорошие идеи.


person SoftwareGeek    schedule 24.07.2010    source источник
comment
@Oded - sql server 2008, исправил название, спасибо.   -  person SoftwareGeek    schedule 24.07.2010
comment
@SoftwareGeek - Из любопытства, что представляют собой данные? Имеет ли буквенный символ особое значение?   -  person Thomas    schedule 24.07.2010
comment
Можете ли вы изменить схему базы данных?   -  person Erick Robertson    schedule 24.07.2010
comment
@Erick - Нет, нельзя изменить схему БД, но в этом нет необходимости.   -  person SoftwareGeek    schedule 25.07.2010
comment
Обновление: мне не хватает оператора вставки в моем образце, чтобы добавить несколько строк.   -  person SoftwareGeek    schedule 25.07.2010


Ответы (3)


Самое простое решение - поставить нули перед

Select ...
From Table
Order By Right( '0000000000' + YourColumn, 10)

Однако это не будет учитывать альфа-символы. Чтобы иметь дело с альфа-символами, вам нужно знать, сколько потенциальных альфа-символов у вас может быть. Если он есть, вы можете сделать что-то вроде:

Select ...
From #Test
Order By Case
    When IsNumeric(NumVal) = 1 Then Right('0000000000' + NumVal + '0', 10)
    Else Right('0000000000' + NumVal, 10)
    End

ДОПОЛНЕНИЕ

Тестовый забег:

If object_id('tempdb..#Test') is not null
    Drop Table #Test

Create Table #Test ( NumVal varchar(10) )
Insert #Test(NumVal) Values('02')
Insert #Test(NumVal) Values('03')
Insert #Test(NumVal) Values('1a')
Insert #Test(NumVal) Values('1b')
Insert #Test(NumVal) Values('10')
Insert #Test(NumVal) Values('11')

Select NumVal
From #Test
Order By Case
    When IsNumeric(NumVal) = 1 Then Right('0000000000' + NumVal + '0', 10)
    Else Right('0000000000' + NumVal, 10)
    End

Results:
1a
1b
02
03
10
11

Заметка о моем решении. Если это так, что буквенные символы имеют особое значение, то, как предложил Эрик Робертсон, вы должны разбить данные на отдельные столбцы. Приведенное выше решение будет обрабатывать только два очень специфических случая: полностью числовое значение, значение с одним завершающим буквенным символом. Если данные могут содержать несколько буквенных символов или буквенный символ иногда расположен не в конце значения, мое решение не будет работать. Кроме того, следует отметить, что мое решение приведет к сканированию таблицы для оценки упорядочиваемой строки для каждого значения.

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

person Thomas    schedule 24.07.2010
comment
Почему бы не поставить «0000000002» перед «000000001a»? - person Erick Robertson; 24.07.2010
comment
@ Эрик Робертсон - пересмотрел мой пост. С первого раза не было возможности во всем разобраться. - person Thomas; 24.07.2010
comment
Это, конечно, уже не кажется самым простым решением. :) - person Erick Robertson; 24.07.2010
comment
@Erick Robertson - определенно не самое быстрое решение. Единственный другой способ - отделить числовые символы от нечисловых, что также не будет быстрым. - person Thomas; 24.07.2010
comment
@Thomas - я попробовал ваше предложение, оно не работает, пожалуйста, посмотрите мое обновление. - person SoftwareGeek; 24.07.2010
comment
@SoftwareGeek - я разместил свой тестовый код. Насколько я могу судить, это работает. - person Thomas; 24.07.2010
comment
Вы выбираете трудный путь, идя по этому пути. Создайте отдельный столбец, напишите сценарий для его заполнения, измените приложение для его обслуживания и сначала упорядочите по этому столбцу. Это будет работать. - person Erick Robertson; 24.07.2010
comment
@SoftwareGeek, @Erick Robertson - я согласен, если изменение схемы возможно. Следует также отметить, что мое решение будет обрабатывать только два очень специфических случая: полностью числовой или одиночный буквенный символ в конце. Если у вас есть такие значения, как «1a10», «1aa» или «a99», это не сработает. - person Thomas; 24.07.2010
comment
@Thomas - значения имеют простую логику. При повторении последовательности он добавляет буквенно-цифровой символ, поэтому упомянутые вами точки данных не возникнут. - person SoftwareGeek; 25.07.2010
comment
@Thomas - А, проблема решена. Мой образец не вставлял все данные в таблицу. Исправлено, но мне любопытно, что заставляет правильно сортировать данные с добавлением «0»? - person SoftwareGeek; 25.07.2010
comment
@Thomas - Можно ли указать порядок сортировки «ASC» или «DESC»? Как это сделать в обратном порядке? - person SoftwareGeek; 25.07.2010
comment
@SoftwareGeek - RE: ASC/DESC, да, вы можете просто добавить DESC к предложению Order By для сортировки по убыванию. Причина добавления нулей в начале заключается в том, что вы сортируете текст, а не числа. Таким образом, значения 1, 10, 2 сортируются в таком порядке, потому что символ 1 сортируется перед 2. Добавление нулей преобразует те же значения выборки во что-то вроде 001, 010, 002, и, таким образом, они сортируются правильно, потому что символ 0 сортируется перед символом 1. . - person Thomas; 25.07.2010

Если вы знакомы с C# или VB.net, возможно, стоит подумать о написании функции CLR, которая выполняет сортировку за вас, поскольку этот порядок сортировки достаточно нестандартен, чтобы его было довольно сложно всесторонне и правильно описать в TSQL.

person Rob    schedule 24.07.2010
comment
да, о.хорошее предложение, но если db может выполнить задачу, я позволю ей справиться с этим. - person SoftwareGeek; 25.07.2010
comment
@SoftwareGeek, я понимаю, о чем вы говорите, но ... функции CLR почти так же хороши, как и TSQL, с точки зрения производительности, и никогда не бывает плохо иметь другой доступный инструмент, особенно тот, который лучше подходит для данной задачи = ) - person Rob; 25.07.2010

Лучшее решение — иметь отдельное поле, в котором хранится значение int токена. Вы должны поддерживать этот столбец при обслуживании столбца токена. Затем, когда вы сортируете, упорядочивайте столбец значений int, а затем столбец токенов. Это позволит вам индексировать эти столбцы для быстрого поиска данных с большими наборами данных.

Функции преобразования из альфы в int работают медленно и не могут использовать преимущества индексации для ускорения запросов. По мере роста вашего набора данных этот тип решения будет только замедляться и загружать вашу базу данных.

person Erick Robertson    schedule 24.07.2010
comment
с уважением, я должен не согласиться. Должен быть лучший способ. Мне нравится решение здесь, оно работает. С другой стороны, я бы также согласился с предложением @Rob. - person SoftwareGeek; 25.07.2010
comment
@SoftwareGeek - лучший способ сделать это - использовать индексы базы данных. Конечно, если у вас нет доступа для изменения базы данных, то о лучшем решении не может быть и речи. Разработчик базы данных должен был понимать, что люди захотят получать данные с помощью этого метода, и разработать его соответствующим образом. - person Erick Robertson; 25.07.2010