Стандартизируйте числовые форматы из разных регионов - PullRequest
0 голосов
/ 05 июля 2018

Я выполняю масштабную очистку в старой системе, и у меня есть таблица базы данных SQL Server со столбцом типа TEXT, где хранятся числовые (включая денежные) данные (а также текстовые данные), часто в локализованный формат или опечатка ужасно. Мне нужно стандартизировать данные в соответствии с американскими цифровыми стандартами.

Примеры некоторых данных:

$1,000 - Good!
$1.000 - Bad, should have been $1,000
$1,000.000 - Bad, should have been $1,000,000
$1,000.000.00 - Bad, should have been $1,000,000.00
$1.000.000,00 - Bad, should have been $1,000,000.00
$10,.000 - Bad, should have been $10,000
500.000 - Bad, should have been 500,000
1.325% - Good!

Я привел несколько примеров, потому что хотел проиллюстрировать некоторые трудности в поиске и исправлении проблем. Я исходил из того, что точка, за которой следуют 3 цифры, должна была быть запятой (если, возможно, это был не точный%, а не $), но точка, за которой следовали 2 цифры, была правильной. У кого-нибудь есть предложения по очистке этого в SQL или нестандартном решении, которое может быть лучше?

Ответы [ 2 ]

0 голосов
/ 05 июля 2018

Чтобы расширить мой ранее опубликованный комментарий:

Для однократного преобразования существующих данных в новый формат вы можете решить проблему следующим образом:

Добавить столбец, который может содержать пустые значения, с соответствующим числовым типом данных, например Decimal(16,4), инициализируется значением NULL.

Дополнительные столбцы могут быть полезны в зависимости от семантики существующих данных. Может иметь смысл захватывать юниты, например Доллары США или проценты, а также шкала, то есть количество мест справа от радикальной точки.

Начните преобразовывать данные по одному шагу за раз. Сначала можно обойтись без коротких и простых шаблонов, например ::1010*

-- Process "$n.nn".
update MyTable
  set DecimalValue = Cast( TextValue as Decimal(16,4) ),
    Unit = 'USD', Scale = 2 -- If desired.
  where DecimalValue is NULL and TextValue like '$[0-9].[0-9][0-9]';

Совет: сохраните операторы в хранимой процедуре или текстовом файле, чтобы вы могли сбросить преобразованные данные и начать все заново по мере накопления мудрости.

Более сложные данные потребуют дополнительной логики преобразования, например ::11015.

-- Process "$n.nnn,nn".
update MyTable
  set DecimalValue = Cast( Replace( Replace( TextValue, '.', '' ), ',', '.' ) as Decimal(16,4) )
  where DecimalValue is NULL and TextValue like '$[0-9].[0-9][0-9][0-9],[0-9][0-9]';

Шаблоны могут быть объединены в одном выражении, где это необходимо:

-- Process ".nn%", "n.nn%" and "nn.nn%".
update MyTable
  set DecimalValue = Cast( Replace( TextValue, '%', '' ) as Decimal(16,4) ),
    Unit = 'percent', Scale = 2 -- If desired.
  where DecimalValue is NULL and (
    TextValue like '.[0-9][0-9]*%' escape '*' or
    TextValue like '[0-9].[0-9][0-9]*%' escape '*' or
    TextValue like '[0-9][0-9].[0-9][0-9]*%' escape '*' );

По мере выполнения преобразований вы можете просмотреть оставшиеся текстовые значения, where DecimalValue is NULL, чтобы увидеть, какие шаблоны имеют смысл, что преобразовывать вручную и какие данные просто не подлежат восстановлению.

0 голосов
/ 05 июля 2018

Я согласен с Шоном и Шнуго, это поможет вам начать, но также подскажет, как легко он может потерпеть неудачу. Все, кроме типов проблем в данных примера, может вызвать проблемы.

declare @table table (ID int identity (1,1), c1 varchar(64))
insert into @table
values
('$1,000'), --good
('$1.000'), -- Bad, should have been $1,000
('$1,000.000'), -- Bad, should have been $1,000,000
('$1,000.000.00'), -- Bad, should have been $1,000,000.00
('$10,.000'), -- Bad, should have been $10,000
('500.000'), -- Bad, should have been 500,000
('1.325%'), -- Good!
('1,325%') -- bad!

select
    *,
    case
        when c1 like '%\%%' escape '\' then replace(c1,',','.') --simply replaces commas with periods for % signed values
        else 
            case                                                --simply replaces periods for commans for non % signed values, and takes into account ,00 at the end should be .00
                                                                --also handles double commas, once
                when left(right(replace(replace(c1,'.',','),',,',','),3),1) = ','
                then stuff(replace(replace(c1,'.',','),',,',','),len(replace(replace(c1,'.',','),',,',',')) - 2,1,'.')
                else replace(replace(c1,'.',','),',,',',')      
            end 
    end
from @table
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...