Уменьшите перегрузку на pl / sql - PullRequest
0 голосов
/ 25 мая 2018

У меня есть требование выполнить сопоставление нескольких атрибутов по одному.Я стараюсь избегать множественных операторов выбора.Ниже приведен пример.

    Table1
    Col1|Price|Brand|size
    -----------------------
    A|10$|BRAND1|SIZE1
    B|10$|BRAND1|SIZE1
    C|30$|BRAND2|SIZE2
    D|40$|BRAND2|SIZE4


    Table2
    Col1|Col2|Col3
    --------------
    B|XYZ|PQR
    C|ZZZ|YYY


    Table3
    Col1|COL2|COL3|LIKECOL1|Price|brand|size
    -----------------------------------------
    B|XYZ|PQR|A|10$|BRAND1|SIZE1
    C|ZZZ|YYY|D|NULL|BRAND2|NULL

В таблице 3 мне нужно вставить данные из таблицы2, проверив следующие условия.

  1. Найти соответствие для записи в таблице 2, если Марка и размер, Цена совпадения
  2. Если совпадений не найдено, попробуйте просто Марка, Размер
  3. По-прежнему не найдено совпадений, попробуйте только марки

В приведенном выше примере дляпервая запись в таблице 2, найдена совпадающая со всеми 3 атрибутами и, таким образом, вставленная в таблицу 3 и вторая запись, запись «D» совпадает, но только «марка».

Все, что я могу придумать, - это написать 3 разных оператора вставкикак ниже в блок Oracle / PLL.

 insert into table3 
   select from tab2 
    where all 3 attributes are matching;

 insert into table3 
   select from tab2 
    where brand and price are matching 
      and not exists in table3 (not exists is to avoid 
                                inserting the same record which was already 
                                inserted with all 3 attributes matched);

 insert into table3 
   select from tab2 
    where Brand is matching and not exists in table3;

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

Ответы [ 2 ]

0 голосов
/ 25 мая 2018

Это случай для OUTER APPLY.

OUTER APPLY - это тип бокового соединения, которое позволяет вам объединяться в динамических представлениях, которые ссылаются на таблицы, появлявшиеся ранее в предложении FROM.С помощью этой способности вы можете определить динамическое представление, которое находит все совпадения, сортирует их по указанному вами порядку размещения, а затем с помощью FETCH FIRST 1 ROW ONLY включает только 1-е в результаты.

ИспользованиеOUTER APPLY означает, что если совпадений нет, вы все равно получите запись таблицы B - просто со всеми столбцами совпадений null.Если вы этого не хотите, вы можете изменить OUTER APPLY на CROSS APPLY.

Вот рабочий пример (с пошаговыми комментариями), бесстыдно украдя сценарии создания таблицы из ответа Михаила Пьянкова:

create table Table1 (Col1,Price,Brand,size1)
as select 'A','10','BRAND1','SIZE1' from dual union all
   select 'B','10','BRAND1','SIZE1' from dual union all
   select 'C','30','BRAND2','SIZE2' from dual union all
   select 'D','40','BRAND2','SIZE4'from dual 

create table Table2(Col1,Col2,Col3)
as select 'B','XYZ','PQR' from dual union all 
   select'C','ZZZ','YYY' from dual;

-- INSERT INTO table3
SELECT t2.col1, t2.col2, t2.col3,
t1.col1 likecol1, 
decode(t1.price,t1_template.price,t1_template.price, null) price,
decode(t1.brand,t1_template.brand,t1_template.brand, null) brand,
decode(t1.size1,t1_template.size1,t1_template.size1, null) size1
FROM 
-- Start with table2
table2 t2
-- Get the row from table1 matching on col1... this is our search template
inner join table1 t1_template on
t1_template.col1 = t2.col1
-- Get the best match from table1 for our search 
-- template, excluding the search template itself
outer apply ( 
SELECT * FROM table1 t1 
WHERE 1=1
-- Exclude search template itself
and t1.col1 != t2.col1
-- All matches include BRAND
and t1.brand = t1_template.brand
-- order by match strength based on price and size
order by case when t1.price = t1_template.price and t1.size1 = t1_template.size1 THEN 1
when t1.size1 = t1_template.size1 THEN 2
else 3 END
-- Only get the best match for each row in T2
FETCH FIRST 1 ROW ONLY) t1;
0 голосов
/ 25 мая 2018

К сожалению, не ясно, что вы имеете в виду, когда говорите матч.Чего вы ожидаете, если будет более одного матча?Это должно быть только первое совпадение или оно сгенерирует все доступные пары?

Что касается вашего вопроса, как избежать множественных вставок, существует более одного способа:

  1. Вы можете использовать множественную вставку с INSERT first и условием.
  2. Вы можете присоединиться к table1 для себя и получить все пары и отфильтровать результаты, где условие
  3. Вы можете использовать аналитическую функцию
  4. Я полагаю, есть и другие способы.Но почему вы хотели бы избежать 3 простых вставок.Его легко читать и поддерживать.И может быть

Вот пример с аналитической функцией следующий:

create table Table1 (Col1,Price,Brand,size1)
as select 'A','10','BRAND1','SIZE1' from dual union all
   select 'B','10','BRAND1','SIZE1' from dual union all
   select 'C','30','BRAND2','SIZE2' from dual union all
   select 'D','40','BRAND2','SIZE4'from dual 

create table Table2(Col1,Col2,Col3)
as select 'B','XYZ','PQR' from dual union all 
   select'C','ZZZ','YYY' from dual

with s as (
select Col1,Price,Brand,size1, 
        count(*) over(partition by Price,Brand,size1 ) as match3, 
        count(*) over(partition by Price,Brand ) as match2,
        count(*) over(partition by Brand ) as match1,
        lead(Col1) over(partition by Price,Brand,size1 order by Col1) as like3, 
        lead(Col1) over(partition by Price,Brand order by Col1) as like2,
        lead(Col1) over(partition by Brand order by Col1) as like1,
        lag(Col1) over(partition by Price,Brand,size1 order by Col1) as like_desc3, 
        lag(Col1) over(partition by Price,Brand order by Col1) as like_desc2,
        lag(Col1) over(partition by Brand order by Col1) as like_desc1
from Table1 t )
select t.Col1,t.Col2,t.Col3, coalesce(s.like3, like_desc3, s.like1, like_desc1, s.like1, like_desc1),
    case when  match3 > 1 then size1 end as size1,
    case when  match1 > 1 then Brand end as Brand,
    case when  match2 > 1 then Price end as Price
        from table2 t
         left join s on s.Col1 = t.Col1 

COL1    COL2    COL3    LIKE_COL    SIZE1   BRAND   PRICE
B   XYZ PQR A   SIZE1   BRAND1  10
C   ZZZ YYY D    -  BRAND2   - 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...