Разделить записи в одном столбце на несколько столбцов - PullRequest
0 голосов
/ 15 мая 2019

Я не уверен, достижимо ли это на сервере sql или нет.У меня есть таблица ADDRESS и ее метаданные приведены ниже.SQ_ID - это мой уникальный ключевой столбец

SQ_ID INT
ADDRESS_LINE_1 varchar(255)
ADDRESS_LINE_2 varchar(255)
ADDRESS_LINE_3 varchar(255)
ADDRESS_LINE_4 varchar(255)
REGION varchar(255)
POSTOCODE varchar(255)
COUNTRY_CODE varchar(255)

Теперь я загрузил около 2 миллионов записей в эту таблицу, и проблема в том, что все детали адреса были загружены в столбец ADDRESS LINE 1 в этой таблице.Сейчас я пытаюсь найти способ разделить это.Ниже приведен пример набора адресов.

enter image description here

Поэтому я хочу разбить данные в строке адреса 1 таким образом, чтобы

значение в addressLine1 в данной записи должно быть заполнено до addressline1 в том же значении таблицы в addressLine2 в данной записи должно быть заполнено в addressline2 в том же значении таблицы в addressLine3 в данной записи должно быть заполнено доaddressline3 в том же значении таблицы в primaryTown в данной записи должен быть заполнен до addressline4 в том же значении таблицы в ProvinceOrState в данной записи должен быть заполнен в регион в том же значении таблицы в isoAlpha2Code в данной записи должен быть заполнен COUNTRY_CODE вто же самое табличное значение в zipOrPostalCode в данной записи должно быть заполнено до POSTOCODE в той же таблице

Мой ожидаемый вывод приведен ниже

enter image description here

Кроме того, я прилагаю набор значений примеров адресов для тестатинг

{'addressLine1': '67 xxxx Road', 'primaryTown': 'HOxxxCHxxCH',
 'zipOrPostalCode': 'RM11 1EX', 'addressCountry': {'isoAlpha2Code':
 'GB'}}

{'primaryTown': 'MünXXer', 'addressCountry': {'isoAlpha2Code': 'DE'}}

{'addressLine1': '28 THE EXCAC', 'primaryTown': 'PERTH',
'provinceOrState': 'WA', 'addressCountry': {'isoAlpha2Code': 'AU'}}

{'addressLine1': '28 THE ESPLANADE', 'primaryTown': 'PERTH',
'provinceOrState': 'WA', 'addressCountry': {'isoAlpha2Code': 'AU'}}

{'addressLine1': '76 XXX STREET', 'primaryTown': 'MAXDFOT',
'provinceOrState': 'NSW', 'addressCountry': {'isoAlpha2Code': 'AU'}}

{'addressLine1': 'UNIT 56', 'addressLine2': '22 XDFR STREET',
'primaryTown': 'MANLY VALE', 'provinceOrState': 'NSW',
'addressCountry': {'isoAlpha2Code': 'AU'}}

{'addressLine1': 'BjoXCDSaret 15', 'addressLine2': 'Jppsdeheim',
'addressLine3': '', 'primaryTown': 'AKERdwfUS', 'addressCountry':
{'isoAlpha2Code': 'NO'}}

1 Ответ

2 голосов
/ 15 мая 2019

Вы не можете разобрать JSON, разделив.SQL Server 2016 и более поздние версии поддерживают JSON, поэтому вы можете извлекать нужные данные, используя такие функции, как JSON_VALUE .

У вас нет , чтобы сделать это,если вы не хотите индексировать и фильтровать эти значения.Возможно, имеет смысл извлечь страну или почтовый индекс, если вы собираетесь фильтровать или группировать результаты, используя их.Адресные строки, с другой стороны, не могут быть запрошены и могут также оставаться в строке JSON.Вы всегда можете извлечь их при необходимости с помощью JSON_VALUE.

Puttin primaryTown in AddressLine4 выглядит как ошибка.Это является значимым атрибутом, который можно использовать при запросах.Он должен идти на свое поле или вообще не добываться.

SQL Server 2016 и более поздние версии

В любом случае вы можете проанализировать значение JSON с помощью JSON_VALUE, например:

declare @myTable table(json varchar(max))

insert into @myTable
values
('{"addressLine1": "BjoXCDSaret 15", "addressLine2": "Jppsdeheim","addressLine3": "", "primaryTown": "AKERdwfUS", "addressCountry":
{"isoAlpha2Code": "NO"}}'),
('{"addressLine1": "67 xxxx Road", "primaryTown": "HOxxxCHxxCH",
 "zipOrPostalCode": "RM11 1EX", "addressCountry": {"isoAlpha2Code":
 "GB"}}'),
('{"primaryTown": "MünXXer", "addressCountry": {"isoAlpha2Code": "DE"}}'),
('{"addressLine1": "28 THE EXCAC", "primaryTown": "PERTH",
"provinceOrState": "WA", "addressCountry": {"isoAlpha2Code": "AU"}}'),
('{"addressLine1": "28 THE ESPLANADE", "primaryTown": "PERTH",
"provinceOrState": "WA", "addressCountry": {"isoAlpha2Code": "AU"}}'),
('{"addressLine1": "76 XXX STREET", "primaryTown": "MAXDFOT",
"provinceOrState": "NSW", "addressCountry": {"isoAlpha2Code": "AU"}}'),
('{"addressLine1": "UNIT 56", "addressLine2": "22 XDFR STREET",
"primaryTown": "MANLY VALE", "provinceOrState": "NSW",
"addressCountry": {"isoAlpha2Code": "AU"}}')

select 
    JSON_VALUE(json,'$.zipOrPostalCode') as ZipCode,
    JSON_VALUE(json,'$.primaryTown') as primaryTown,
    JSON_VALUE(json,'$.addressCountry.isoAlpha2Code') as CountryCode
from @mytable

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

Старые версии

В старых версиях, возможно, самым простым решением было бы создание функции SQLCLR, которая использует JSON.NET для анализа данных и возврата значений.

Другой вариант - преобразовать строку JSON в XML с помощью замены строк и использовать XPATH для получения значений.Это может быть очень сложно, хотя замены зависят от ожидаемых данных, чувствительны к пробелам и могут легко сломаться при работе с вложенными объектами.

Например, этот плоский объект JSON:

declare @json varchar(max)='{"addressLine1": "BjoXCDSaret 15", "addressLine2": "Jppsdeheim", "addressLine3": "", "primaryTown": "AKERdwfUS"}'

Может быть преобразован в XML с несколькими заменами.Обратите внимание, что я исправил различия между пробелами, чтобы между токенами всегда было пространство.В противном случае мне пришлось бы заменить оба "," и ", ".

select 
    cast(
        replace(
            replace(
                replace(
                    replace(@json,'{"','<it '),
                '": "',' ="'),
            '", "','" '),
        '}',' />')
    as xml)

Результат:

<it addressLine1="BjoXCDSaret 15" addressLine2="Jppsdeheim" addressLine3="" primaryTown="AKERdwfUS" />

Теперь это можно запросить с помощью .value :

select 
    cast(replace(replace(replace(replace(@json,'{"','<it '),'": "',' ="'),'", "','" '),'}',' />') as xml)       
     .value('(/it/@primaryTown)[1]','varchar(20)')

Это вернет:

AKERdwfUS

Это разрывается с вложенным объектом addressCountry.Если вы знаете , что содержит текст JSON, вы можете использовать читы и заменять определенные атрибуты, а не только разделители, например:

declare @json varchar(max)='{"addressLine1": "UNIT 56", "addressLine2": "22 XDFR STREET", "primaryTown": "MANLY VALE", "provinceOrState": "NSW", "addressCountry": {"isoAlpha2Code": "AU"}}'
select      
cast(
    replace(
        replace(
            replace(
                replace(
                    replace(
                        replace(@json,'", "addressCountry": {"','"><addressCountry '),
                        '}}','/></it>'),
                    '{"','<it '),
                '": "',' ="'),
            '", "','" ')
        ,'}',' />') 
    as xml).value('(/it/addressCountry/@isoAlpha2Code)[1]','varchar(20)')

Возвращает AU.

Это серьезный обман, который может работать только методом проб и ошибок.В этом случае атрибут addressCountry и следующие разделители преобразуются в элемент.Ожидается, что }} появится только в конце строки, поэтому он получает специальную обработку.

Использование клиентского скрипта

Вероятно, проще использовать небольшую программу .NET для чтения данных с использованием JSON.NET и извлечения нужных значений.2М строк не так много, поэтому анализ данных время от времени не будет большой проблемой

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...