Столбец «Разделить имя», который может содержать несколько имен и без разделителя на Персона 1 и Персона 2 - PullRequest
0 голосов
/ 21 апреля 2020

Как мне разбить строку, которая может содержать 2 имени на Person1 и Person2? Между именами нет разделителя, для каждой строки не всегда есть второй человек и необязательно средний инициал / имя для первого или второго человека, и только иногда второе имя будет разделено знаком «И». Примеры имен следующим образом

  • ДЖЕЙН МИДДЛЕТОН Джон МИДДЛЕТОН
  • СЮ ФРАКАРО БОБ ФРАКАРО
  • ТОНИ ФРАНЦУЗСКИЙ
  • ДЖОН ЭДУАРДО ОХОА И ДЖЕЙН АДРИАНА ОХОА
  • TONY JOHN CARPENTER TONYA CARPENTER

Желаемый дизайн выхода

  • Персона 1 Имя
  • Персона 1 Отчество
  • Персона 1 Фамилия
  • Персона 2 Имя
  • Персона 2 Отчество
  • Персона 2 Фамилия

1 Ответ

0 голосов
/ 22 апреля 2020

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

CREATE FUNCTION [dbo].[Fn_Splittemp]
        (
          @text VARCHAR(8000)
        , @delimiter VARCHAR(20) = ' '
        )
        RETURNS @String TABLE
            (
                  Position INT IDENTITY PRIMARY KEY
                , StringValue VARCHAR(8000)
            )
        AS
        BEGIN
            DECLARE @index INT
            SET @index = -1
            WHILE (LEN(@text) >0)
                    BEGIN
                        SET @index = CHARINDEX(@delimiter, @text)
                            IF (@index = 0) AND (LEN(@text) > 0)
                                BEGIN
                                    INSERT INTO @string VALUES (@text)
                                    BREAK
                                END
                            IF (@index > 1)
                                BEGIN
                                    INSERT INTO @String VALUES (LEFT(@text, (@index-1)))
                                    SET @text = RIGHT(@text, (LEN(@text)-@index))
                                END
                            ELSE
                                    SET @text = RIGHT(@text, (LEN(@text)-@index))
                                END
                        RETURN
                    END
    GO

Разделение, очистка и присвоение соответствующим столбцам name_columns:

CREATE TABLE #t0 (rid INT IDENTITY, rawnames VARCHAR(8000));
GO

INSERT INTO #t0 VALUES ('JANE MIDDLETON John MIDDLETON'),
('SUE FRACARO BOB FRACARO'),
('TONY FRENCH'),
('JOHN EDUARDO OCHOA AND JANE ADRIANA OCHOA'),
('TONY JOHN CARPENTER TONYA CARPENTER');
GO

SELECT n.rid, n.rawnames, fn.StringValue AS Names, 
COUNT(*) OVER(PARTITION BY rawnames) AS wordcount,
ROW_NUMBER() OVER(PARTITION BY fn.stringvalue,rawnames ORDER BY fn.stringvalue) AS LastNameids,
fn.Position
INTO #t1
FROM #t0 n
cross apply dbo.Fn_Splittemp(n.rawnames, ' ') AS fn
GO

SELECT rid, rawnames, Position AS Pid, 
PersonName, LastName INTO #t2
FROM
(SELECT t.rid, t.rawnames, t.names AS Lastname, LTRIM(RTRIM(REPLACE(f.StringValue,'and',''))) AS PersonName, f.Position
FROM
    (SELECT replace(sqa.rawnames,sqa.Names,sqa.Names+',') AS delimstr , sqa.* 
        FROM #t1 sqa
        WHERE wordcount<=3 AND position = (SELECT MAX(position) from #t1 crq where crq.rid = sqa.rid)
    )t
cross apply dbo.Fn_Splittemp(delimstr,',') f
UNION ALL
SELECT b.rid, b.rawnames, b.Names AS Lastname, LTRIM(RTRIM(REPLACE(f.StringValue,'and',''))) AS PersonName, f.Position
FROM 
(SELECT replace(rawnames,names,names+',') AS delimstr, *
FROM #t1 
WHERE wordcount>3 AND LastNameids>1)b
cross apply dbo.Fn_Splittemp(delimstr,',') f
)sqt
GO

SELECT * INTO #t3 FROM #t2 cross apply dbo.Fn_Splittemp(personname, ' ');
GO

SELECT t.rawnames, fina.Firstname, fina.MiddleName, fina.LastName
FROM #t0 t
JOIN (
SELECT rid, pid, [1] AS Firstname, NULL AS MiddleName, [2] AS LastName 
FROM
(SELECT * FROM (SELECT rid, pid, position, stringvalue, 
COUNT(*) OVER(PARTITION BY rid, pid) AS cnt FROM #t3)a
WHERE a.cnt <=2)apiv
PIVOT
(MAX(stringvalue)
    FOR position IN ([1],[2])
    )piva
UNION ALL
SELECT rid, pid, [1] AS Firstname, [2] AS MiddleName, [3] AS LastName
FROM
(SELECT * FROM (SELECT rid, pid, position, stringvalue, 
COUNT(*) OVER(PARTITION BY rid, pid) AS cnt FROM #t3)a
WHERE a.cnt >2)apiv
PIVOT
(MAX(stringvalue)
    FOR position IN ([1],[2],[3])
    )piva
)fina
ON fina.rid = t.rid;
...