Разделить столбец адреса на отдельные столбцы в представлении SQL - PullRequest
5 голосов
/ 05 февраля 2010

У меня есть столбец Address в таблице, который мне нужно разделить на несколько столбцов в представлении в SQL Server 2005. Мне нужно разделить столбец по символу перевода строки, chr (10), и может быть от 1 до 4 строк (от 0 до 3 строк) в столбце. Ниже приведено несколько примеров того, что мне нужно сделать. Как проще всего это сделать?

Examples:

Address                 Address1      Address2       Address3            Address4
------------        =   -----------   -----------    -----------------   ---------
My Company              My Company     123 Main St.  Somewhere,NY 12345  
123 Main St.         
Somewhere,NY 12345

Address                 Address1       Address2      Address3      Address4
------------        =   ------------   ----------    -----------   ---------
123 Main St.            123 Main St.

Ответы [ 3 ]

3 голосов
/ 05 февраля 2010

это разделит адрес, используя функцию parsename и объединив ее с COALESCE, чтобы получить правильную информацию в правильном столбце

если у вас более 4 строк, этот метод НЕ будет работать

edit: добавлен код для изменения порядка

    create table #test (address varchar(1000))

    --test data
    insert #test values('My Company
    123 Main St.         
    Somewhere,NY 12345')

    insert #test values('My Company2
    666 Main St.  
    Bla Bla       
    Somewhere,NY 12345')

    insert #test values('My Company2')

    --split happens here
                            select
replace(parsename(address,ParseLen +1),'^','') as Address1,
replace(parsename(address,ParseLen ),'^','') as Address2,
replace(parsename(address,ParseLen -1),'^','') as Address3,
replace(parsename(address,ParseLen -2),'^','') as Address4
from(
select case  ascii(right(address,1)) when 10 then
replace(replace(left(address,(len(address)-1)),'.','^'),char(10),'.')  
else 
replace(replace(address,'.','^'),char(10),'.') end as address,
case  ascii(right(address,1)) when 10 then
len(replace(replace(address,'.','^'),char(10),'.')) -
len(replace(replace(address,'.','^'),char(10),'')) -1
else
len(replace(replace(address,'.','^'),char(10),'.')) -
len(replace(replace(address,'.','^'),char(10),'')) end as ParseLen
 from #test) x
1 голос
/ 05 февраля 2010

Это ужасно неприятно ... Я настоятельно рекомендую, чтобы, если вы хотите обрабатывать каждую адресную строку отдельно, вы должны хранить ее правильно в первую очередь. Вместо того чтобы продолжать делать то, что вы делаете, добавьте дополнительные столбцы, исправьте существующие данные один раз (вместо того, чтобы «исправлять» их каждый раз, когда вы выполняете запрос), а затем настройте хранимую процедуру, которая выполняет вставка / обновление, чтобы он мог использовать другие столбцы.

DECLARE @Address TABLE(id INT IDENTITY(1,1), ad VARCHAR(MAX));

INSERT @Address(ad) SELECT 'line 1
line 2
line 3
line 4'
UNION ALL SELECT 'row 1
row 2
row 3'
UNION ALL SELECT 'address 1
address 2'
UNION ALL SELECT 'only 1 entry here'
UNION ALL SELECT 'let us try 5 lines
line 2
line 3
line 4 
line 5';

SELECT
    id,
    Line1 = REPLACE(REPLACE(COALESCE(Line1, ''), CHAR(10), ''), CHAR(13), ''),
    Line2 = REPLACE(REPLACE(COALESCE(Line2, ''), CHAR(10), ''), CHAR(13), ''),
    Line3 = REPLACE(REPLACE(COALESCE(SUBSTRING(Rest, 1, COALESCE(NULLIF(CHARINDEX(CHAR(10), Rest), 0), LEN(Rest))), ''), CHAR(10), ''), CHAR(13), ''),
    Line4 = REPLACE(REPLACE(COALESCE(SUBSTRING(Rest, NULLIF(CHARINDEX(CHAR(10), Rest) + 1, 1), LEN(Rest)), ''), CHAR(10), ''), CHAR(13), '')
FROM

(
    SELECT 
        id,
        ad,
        Line1,
        Line2 = SUBSTRING(Rest, 1, COALESCE(NULLIF(CHARINDEX(CHAR(10), Rest), 0), LEN(Rest))),
        Rest = SUBSTRING(Rest, NULLIF(CHARINDEX(CHAR(10), Rest) + 1, 1), LEN(Rest))
    FROM
    (
        SELECT
            id,
            ad,
            Line1 = SUBSTRING(ad, 1, COALESCE(NULLIF(CHARINDEX(CHAR(10), ad), 0), LEN(ad))),
            Rest = SUBSTRING(ad, NULLIF(CHARINDEX(CHAR(10), ad) + 1, 1), LEN(ad))
        FROM
            @address
    ) AS x
) AS y
ORDER BY id;

Трюк Дениса PARSENAME (), конечно, намного сложнее, но вы должны быть чрезвычайно осторожны с использованием символа замены, который действительно невозможно естественным образом отобразить в данных. Карат (^), вероятно, хорошая ставка, но, как я уже сказал, вы должны быть осторожны.

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

0 голосов
/ 05 февраля 2010

Разбор текста в SQL - это не весело. Если бы мне пришлось сделать что-то подобное, я бы экспортировал столбец в текстовый файл CSV и проанализировал его на языке сценариев, таких как Perl / PHP / Python. Таким образом, я могу воспользоваться встроенными строковыми функциями и регулярным выражением языка сценариев.

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