Отправляет email-рассылки с помощью сервиса Sendsay

Вопросы и ответы по MS SQL Server

  Все выпуски  

Вопросы и ответы по MS SQL Server


Информационный Канал Subscribe.Ru


Вопросы и ответы по MS SQL Server

Выпуск No. 26 от 2003-12-19

Вопрос : Как отсортировать выборку по символьному полю, содержащему числовые значения?

Ответ:
Одним из примеров хранения числовых величин в символьном поле является хранение номеров документов. В этом случае номера, как правило, числовые, но при этом к номеру могут добавляться произвольные символы. В результате сортировка по этому полю дает нежелательный эффект.
create table #Table(sField varchar(20))

insert #Table values('1234-2ф/25')
insert #Table values('вид1256ь')
insert #Table values('86')
insert #Table values('123')
insert #Table values('a125')
insert #Table values('125б')
insert #Table values('124')
insert #Table values(':-)')
insert #Table values(NULL)

select * from #Table
order by sField

Результат:
sField               

--------------------
NULL
:-)
123
1234-2ф/25
124
125б
86
a125
вид1256ь

(9 row(s) affected)

Полученный результат плох тем, что значение 86 стоит после 123. Исправить это можно только приведя символьные данные к числовым. Если просто использовать функцию CAST или CONVERT, то преобразование символьных величин будет выдавать ошибку и останавливать выполнение.
Стало быть нужно вырезать числовые значения из полного номера документа.
Вот пример функции, которая делает то, что нужно и пример ее использования:
CREATE FUNCTION CharToInt(@s varchar(20))

RETURNS int AS
BEGIN
DECLARE @i int

-- начало числа
SET @i = PATINDEX('%[1234567890]%', @s)
-- строка с начала числа и до конца
SET @s = SUBSTRING(@s, @i, 20)

-- окончание числа
SET @i = PATINDEX('%[^1234567890]%', @s) - 1

-- если есть в конце буквы, то обрезать
IF @i >= 0 SET @s = LEFT(@s, @i)

RETURN (@s)
END
GO
select dbo.CharToInt(sField) as [int], sField
from #Table
order by dbo.CharToInt(sField)

GO

Результат:
int         sField               

----------- --------------------
NULL NULL
0 :-)
86 86
123 123
124 124
125 a125
125 125б
1234 1234-2ф/25
1256 вид1256ь

(9 row(s) affected)

А если Ваша версия MSSQL не позволяет создавать функции, то можно произвести вырезание номера без использования функции:
select *

from #Table
order by CAST(
LEFT(
SUBSTRING(sField, PATINDEX('%[1234567890]%', sField), 20),
ISNULL(NULLIF(
PATINDEX('%[^1234567890]%',
SUBSTRING(sField, PATINDEX('%[1234567890]%', sField), 20)
)-1,
-1),20)
)
as int)

Результат:
sField               

--------------------
NULL
:-)
86
123
124
a125
125б
1234-2ф/25
вид1256ь

(9 row(s) affected)

Генеральный спонсор рассылки - ООО "Софтоматика"
Надеюсь, Вы нашли эту информацию полезной. Вопросы, предложения и пожелания шлите на адрес sql@likor.ru
С уважением, Сергей Кошкин.
Обсудить этот выпуск можно на Форуме рассылки

Архив рассылки смотрите на сайте Рассылки http://sql.softmatics.ru/
Рейтинг@Mail.ru

http://subscribe.ru/
E-mail: ask@subscribe.ru
Отписаться
Убрать рекламу

В избранное