У меня есть столбец данных, содержащий процентный диапазон в виде строки, которую я хотел бы преобразовать в число, чтобы я мог легко сравнивать.
Возможные значения в строке:
'<5%'
'5-10%'
'10-15%'
...
'95-100%'
Я хотел бы преобразовать это в моем предложении select where только в первое число, 5, 10, 15 и т. д., Чтобы я мог сравнить это значение с переданным значением «по крайней мере это».
Я пробовал кучу вариантов подстроки, charindex, convert и replace, но я все еще не могу найти что-то, что работает во всех комбинациях.
Есть идеи?





Вы можете преобразовать данные char в другие типы char (преобразовать char (10) в varchar (10)), но вы не сможете преобразовать символьные данные в целочисленные данные изнутри SQL.
Я не знаю, работает ли это в SQL Server, но в MySQL вы можете использовать несколько приемов для преобразования символьных данных в числа. Примеры из ваших демонстрационных данных:
"<5%" => 0
"5-10%" => 5
"95-100%" => 95
теперь очевидно, что это не соответствует вашему первому тесту, но некоторых умных замен строки в начале строки будет достаточно, чтобы заставить ее работать.
Один пример преобразования символьных данных в числа:
SELECT "5-10%" + 0 AS foo ...
Может не работать в SQL Server, но будущие поиски могут помочь странному пользователю MySQL :-D
Вероятно, вам было бы намного лучше изменить <5% и 5-10% для хранения 2 значений в 2 полях. Вместо хранения <5% вы бы сохранили 0 и 5, а вместо 5-10% вы получите 5 и 10. В итоге вы получите 2 столбца, один называется нижним, а другой верхний, а затем просто проверьте значение >=. нижняя граница И значение < верхняя граница.
Попробуй это,
SELECT substring(replace(interest , '<',''), patindex('%[0-9]%',replace(interest , '<','')), patindex('%[^0-9]%',replace(interest, '<',''))-1) FROM table1
Протестировано на моей стороне, и это работает, это только моя первая попытка, так что вы сможете его оптимизировать.
Вы можете сделать это на сервере sql с помощью курсора. Если вы можете создать функцию CLR для извлечения групп номеров, это поможет. Это возможно в T-SQL, но это будет некрасиво.
Создайте курсор, чтобы перемещаться по списку. Найдите первый номер, если в их группе только 1 номер, верните его. В противном случае найдите вторую группу элементов.
если возвращается только 1-я группа элементов, и ее первый элемент в списке устанавливает его на верхнюю границу. если возвращается только 1-я группа элементов, а ее последний элемент в списке задает для нее нижнюю границу. В противном случае установите 1-ю группу элементов на более низкую, а 2-ю группу элементов на верхнюю границу.
Просто верните полученные значения в таблицу
Проблема, с которой вы столкнулись, является признаком того, что данные не сохраняются атомарно. В этом случае это выглядит совершенно непреднамеренно (устаревшая версия), но вот об этом связь.
Чтобы спроектировать себя из этого, создайте таблицу range_lookup:
Create table rangeLookup(
rangeID int -- or rangeCD or not at all
,rangeLabel varchar(50)
,LowValue int--real or whatever
,HighValue int
)
Если взломать себе здесь несколько псевдо-шагов, это будет глубоко вложенный беспорядок.
normalize your input by replacing all your crazy charecters.
replace(replace(rangeLabel,"%",""),"<","")
--This will entail many nested replace statments.
Add a CASE and CHARINDEX to look for a space if there is none you have your number
else use your substring to take everything before the first " ".
-- theses steps are wrapped around the previous step.
@Martin: Ваше решение работает.
Вот еще один, который я придумал на основе вдохновения @mercutio
select cast(replace(replace(replace(interest,'<',''),'%',''),'-','.0') as numeric) test
from table1 where interest is not null
Это сложно, но для предоставленных вами тестовых примеров это работает. Просто замените @Test столбцом, который вы просматриваете в своей таблице.
DECLARE @TEST varchar(10)
set @Test = '<5%'
--set @Test = '5-10%'
--set @Test = '10-15%'
--set @Test = '95-100%'
Select CASE WHEN
Substring(@TEST,1,1) = '<'
THEN
0
ELSE
CONVERT(integer,SUBSTRING(@TEST,1,CHARINDEX('-',@TEST)-1))
END
AS LowerBound
,
CASE WHEN
Substring(@TEST,1,1) = '<'
THEN
CONVERT(integer,Substring(@TEST,2,CHARINDEX('%',@TEST)-2))
ELSE
CONVERT(integer,Substring(@TEST,CHARINDEX('-',@TEST)+1,CHARINDEX('%',@TEST)-CHARINDEX('-',@TEST)-1))
END
AS UpperBound