Соединить 2 таблицы одним полем, частично сопоставить два других поля - нет декартовых произведений - PullRequest
0 голосов
/ 13 марта 2020

У меня есть 2 таблицы, представляющие замены компонентов в вмешательстве (ID_TK), каждая с номером детали OLD и номером детали NEW, с точки зрения двух разных систем (PN OLD и NEW в одной системе, HW C СТАРЫЙ и НОВЫЙ в другом).

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

ID_SOST - уникальный KEY в первой таблице, PR_ID - уникальный ключ во второй.

Однако только вмешательство id (ID_TK) связывает две таблицы точно. Я должен проверить, соответствуют ли замены в двух таблицах для каждого вмешательства. «Соответствие» означает: один и тот же ID_TK, И PN_OLD должен быть подстрокой (или равной) HWC_OLD, И PN_NEW должен быть подстрокой (или равной) HWC_NEW (обе заглавными буквами):

case 
  when 
   (UPPER(PN_NEW) = UPPER(SUBSTR(HWC_NEW,1,LENGTH(PN_NEW))) AND UPPER(PN_OLD) = UPPER(SUBSTR(HWC_OLD,1,LENGTH(PN_OLD)))) THEN 'YES' else 'NO' as MATCH

enter image description here

В таблице результатов desiderata сначала должны быть перечислены «совпадающие» пары ID_SOST-PR_ID, и они не учитывались для любых других совпадений в ID_TK (лучший вариант - точное матч); остальные несоответствующие пары должны быть перечислены после совпадающих, сначала перечисляя лучшее сходство. Сложность в том, что я не хочу показывать декартово произведение несоответствующих замен (PR и ID_SOST). Кстати, если номер PR (или SOST) отличается, ноль заполнит пропущенные поля.

1 Ответ

0 голосов
/ 13 марта 2020

Итак, во-первых, для дальнейшего использования, вот как привести пример данных в вопросе:

create table table1 (id_tk varchar2(20), id_sost varchar2(20), hwc_old varchar2(20), hwc_new varchar2(20));
create table table2 (id_tk varchar2(20), pr_id varchar2(20), pn_old varchar2(20), pn_new varchar2(20));

insert into table1 values ('TK0000001296676', '00000000199412', '3AL80407AA', '3AL80407AA');
insert into table1 values ('TK0000001296676', '00000000199413', '3AL79090BAAS', '3AL79090BAAS');

insert into table2 values ('TK0000001296676', 'pr-20191025-008', '3AL79090BAAS04', '3AL79090BA');
insert into table2 values ('TK0000001296676', 'pr-20191115-009', '3AL79090BA', '3AL79090BA');
insert into table2 values ('TK0000001296676', 'pr-20191115-011', '3AL79090BAAS04', '3AL79090BA');

Это очень полезно - пожалуйста, не заставляйте нас повторно вводить текст, который у вас уже есть. Просто скопируйте / вставьте данные из Excel.

Для реального запроса - мы выполняем полное внешнее объединение и включаем только те строки, которые либо совпадают, либо имеют нулевые значения вместо совпадений. Мы могли бы также написать это как полное внешнее соединение, исключая декартовы строки продуктов, которые не совпадают.

select nvl(table1.id_tk, table2.id_tk) as id_tk, id_sost, hwc_old, hwc_new, pr_id, pn_old, pn_new,
    case when (UPPER(PN_NEW) = UPPER(SUBSTR(HWC_NEW,1,LENGTH(PN_NEW))) AND UPPER(PN_OLD) = UPPER(SUBSTR(HWC_OLD,1,LENGTH(PN_OLD)))) THEN 'YES' else 'NO' end as MATCH
from table1
full outer join table2
    on (table1.id_tk = table2.id_tk -- display matches if they exist
    and UPPER(PN_NEW) = UPPER(SUBSTR(HWC_NEW,1,LENGTH(PN_NEW))) 
    and UPPER(PN_OLD) = UPPER(SUBSTR(HWC_OLD,1,LENGTH(PN_OLD)))
    ) OR ( -- also include rows with no matches
        (id_sost is null or pr_id is null))
order by MATCH desc -- show matches first
;

Вывод - мой вывод немного отличается от вашего, потому что я не думаю, что вы действительно хочу иметь несовпадающие данные ID_SOST - PR_ID в одной строке. Это трудно сделать в SQL, и я думаю, что этот способ более понятен, так как данные таблицы1 / таблицы2 в строке не совпадают друг с другом.

ID_TK           ID_SOST HWC_OLD         HWC_NEW         PR_ID           PN_OLD          PN_NEW      MATCH
TK0000001296676 199413  3AL79090BAAS    3AL79090BAAS    pr-20191115-009 3AL79090BA      3AL79090BA  YES
TK0000001296676 null    null            null            pr-20191115-011 3AL79090BAAS04  3AL79090BA  NO
TK0000001296676 null    null            null            pr-20191025-008 3AL79090BAAS04  3AL79090BA  NO
TK0000001296676 199412  3AL80407AA      3AL80407AA      null            null            null        NO
...