Как объединить столбцы, содержащие строки, которые не являются точными совпадениями в SQL Server? - PullRequest
1 голос
/ 17 мая 2019

Я пытаюсь создать простое объединение таблиц по столбцам из двух таблиц, которые эквивалентны, но не являются точными совпадениями. Например, значением строки в таблице A может быть «Производство Грузии», а соответствующим значением строки в таблице B может быть «Компания независимого производства Грузии».

Я впервые попробовал подстановочный знак в соединении так:

select BOLFlatFile.*, customers.City, customers.FEIN_Registration_No, customers.ST

 from BOLFlatFile

 Left Join Customers on (customers.Name Like '%'+BOLFlatFile.Customer+'%');

и это прекрасно работает для 90% данных. Однако, если строка в таблице A точно не отображается в таблице B, она возвращает null.

Итак, вернемся к приведенному выше примеру, если бы значение для таблицы A было «Georgia Independent», оно бы работало, но если бы это было «Georgia Production», оно бы не работало.

Ответы [ 2 ]

0 голосов
/ 18 мая 2019

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

Пример ниже будет соответствовать любому, где все слова в поле BOLFlatFile customer содержатся в поле customers name (примечание: это не будет учитывать порядок строк).

Приведенный ниже код будет соответствовать первым двум строкам, как и ожидалось, но не последним двум строкам примера.

CREATE TABLE BOLFlatFile
(
    [customer] NVARCHAR(500)
)

CREATE TABLE Customers
(
    [name] NVARCHAR(500)
)


INSERT INTO Customers VALUES ('Georgia Independent Production Co')
INSERT INTO BOLFlatFile VALUES ('Georgia Production')
INSERT INTO Customers VALUES ('Test String 1')
INSERT INTO BOLFlatFile VALUES ('Test 1')
INSERT INTO Customers VALUES ('Test String 2')
INSERT INTO BOLFlatFile VALUES ('Test 3')

;with BOLFlatFileSplit
as
(
    SELECT *, 
        COUNT(*) OVER(PARTITION BY [customer]) as [WordsInName]
    FROM 
        BOLFlatFile
    CROSS APPLY 
        STRING_SPLIT([customer], ' ')
),
CustomerSplit as 
(
    SELECT *
    FROM 
        Customers
    CROSS APPLY 
        STRING_SPLIT([name], ' ')
)
SELECT 
    a.Customer, 
    b.name
FROM 
    CustomerSplit b
INNER JOIN 
    BOLFlatFileSplit a
ON 
    a.value = b.value
GROUP BY 
    a.Customer, b.name
HAVING 
    COUNT(*) = MAX([WordsInName])
0 голосов
/ 17 мая 2019

Это может быть сложный способ ошибиться, но это работает с образцом, который я смоделировал.

Предполагается, что, поскольку вы "подстановочный поиск" строки из одной таблицы в другую, я предполагаю, что все слова в первом столбце таблицы появляются во втором столбце таблицы, что по умолчанию означает, что вторая таблица В столбце всегда будет более длинная строка, чем в первом столбце таблицы.

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

Приведенный ниже подход сначала создает некоторые примерные данные (я использовал tablea и tableb для представления ваших таблиц).

Затем создается фиктивная таблица для хранения uniqueid для вашей первой таблицы и столбца строки.

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

Следующий раздел соединяет первую таблицу с таблицей обработчиков с использованием уникального идентификатора, а затем присоединяет вторую таблицу к таблице обработчиков по ключевым словам длиной более 3 букв (избегая "" "и" и т. Д.), Присоединяясь к В первой таблице используется предположение, что строка в таблице b длиннее таблицы a (поскольку вы ищете экземпляры каждого слова в таблице столбца в соответствующем столбце таблицы b, отсюда и предположение).

declare @tablea table (
    id int identity(1,1),
    helptext nvarchar(50)
);


declare @tableb table (
    id int identity(1,1),
    helptext nvarchar(50)
);

insert @tablea (helptext)
values
('Text to find'),
('Georgia Production'),
('More to find');

insert @tableb (helptext)
values
('Georgia Independent Production'),
('More Text to Find'),
('something Completely different'),
('Text to find');

declare @stringtable table (
    id int,
    string nvarchar(50)
);

declare @stringmatch table (
    id int,
    stringmatch nvarchar(20)
);

insert @stringtable (id, string)
select id, helptext from @tablea;

update @stringtable set string = string + ' ';

while exists (select 1 from @stringtable)
    begin
        insert @stringmatch (id, stringmatch)
        select id, substring(string,1,charindex(' ',string)) from @stringtable;
        update @stringmatch set stringmatch = ltrim(rtrim(stringmatch));
        update @stringtable set string=replace(string, stringmatch, '') from @stringtable tb inner join @stringmatch ma
        on tb.id=ma.id and charindex(ma.stringmatch,tb.string)>0;
        update @stringtable set string=LTRIM(string);
        delete from @stringtable where string='' or string is null;
    end


        select a.*, b.* from @tablea a inner join @stringmatch m on a.id=m.id
        inner join @tableb b on CHARINDEX(m.stringmatch,b.helptext)>0 and len(b.helptext)>len(a.helptext);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...