Ваша БД, очевидно, является результатом какого-то опроса и, похоже, содержит исходные данные опроса. Обычный способ - выполнить это через процесс ECCD (Извлечь, Очистить, Соответствовать, Доставить) и сохранить чистые и стандартизированные данные в отдельной базе данных (возможно, в хранилище), которую затем можно использовать для аналитики и создания отчетов.
Если у вас есть SSIS, используйте задачу профилирования данных, чтобы получить представление о типах строк, которые у вас там есть. Профиль шаблона столбца сообщает о наборе регулярных выражений в столбце строки, поэтому вы получите представление о том, что находится внутри этих строк. Если у вас нет SSIS, вы можете использовать eobjects DataCleaner , чтобы сделать то же самое.
Если вы не можете сохранить новую базу данных или хотя бы новую таблицу - как минимум добавьте числовой столбец в эту таблицу, а затем извлеките числовые значения из этих строк в новый столбец. Вы можете использовать «что-то еще» (SSIS, Pentaho Kettle, Python, VB, C #) для этого - в общем, T-SQL не очень хорош в обработке строк.
Я предполагаю, что это не единственный столбец с мусором внутри, поэтому любой анализ, который вы можете выполнить на этом, может быть бесполезным.
И если вы все еще думаете, что диапазоны являются единственной проблемой, этот пример может помочь:
Первые данные
DECLARE @myTable TABLE (
AlUnits varchar(10)
) ;
INSERT INTO @myTable
(AlUnits )
VALUES ( '10' )
, ( '15' )
, ( '20' )
, ( '7 - 12' )
, ( '3 - 5' )
;
Запрос разбивает записи на две группы, числовые и не числовые - предполагаемые диапазоны.
;
WITH is_num
AS ( SELECT CAST(AlUnits AS decimal(6, 2)) AS Units_LO
,CAST(AlUnits AS decimal(6, 2)) AS Units_HI
FROM @myTable
WHERE ISNUMERIC(AlUnits) = 1
),
is_not_num
AS ( SELECT CAST( RTRIM(LTRIM(LEFT(AlUnits,
CHARINDEX('-', AlUnits) - 1)))
AS decimal(6,2)) AS Units_LO
,CAST(RTRIM(LTRIM(RIGHT(AlUnits,
LEN(AlUnits)
- CHARINDEX('-', AlUnits))))
AS decimal(6,2)) AS Units_HI
FROM @myTable
WHERE ISNUMERIC(AlUnits) = 0
)
SELECT Units_LO
,Units_HI
,CAST(( Units_LO + Units_HI ) / 2.0 AS decimal(6, 2)) AS Units_Avg
FROM is_num
UNION ALL
SELECT Units_LO
,Units_HI
,CAST(( Units_LO + Units_HI ) / 2.0 AS decimal(6, 2)) AS Units_Avg
FROM is_not_num ;
Возвращает:
Units_LO Units_HI Units_Avg
----------- ----------- ----------
10.00 10.00 10.00
15.00 15.00 15.00
20.00 20.00 20.00
7.00 12.00 9.50
3.00 5.00 4.00