застрял в постановке задачи, которая состоит из сравнения данных для двух таблиц - PullRequest
0 голосов
/ 22 сентября 2018

PFB постановка задачи.Я попытался с использованием параметра density_rank, сохраняю функцию, но каким-то образом я не могу ее взломать.Может кто-нибудь, пожалуйста, помогите.Это небольшой набор данных для представления проблемы.Оригинальные таблицы имеют несколько миллионов строк.

сценарии для набора данных:

CREATE TABLE TRANSACTION (  
    ITEM VARCHAR2(25 BYTE), 
    LOCATION NUMBER(10,0), 
    TRAN_DATE DATE, 
    POST_DATE DATE 
) 


Insert into TRANSACTION (ITEM,LOCATION,TRAN_DATE,POST_DATE) values ('13252099',473,to_date('09-JUL-18','DD-MON-RR'),to_date('09-JUL-18','DD-MON-RR'));
Insert into TRANSACTION (ITEM,LOCATION,TRAN_DATE,POST_DATE) values ('13252099',473,to_date('25-JUL-18','DD-MON-RR'),to_date('25-JUL-18','DD-MON-RR'));
Insert into TRANSACTION (ITEM,LOCATION,TRAN_DATE,POST_DATE) values ('13252098',470,to_date('09-JUL-18','DD-MON-RR'),to_date('09-JUL-18','DD-MON-RR'));
Insert into TRANSACTION (ITEM,LOCATION,TRAN_DATE,POST_DATE) values ('13252098',470,to_date('28-JUL-18','DD-MON-RR'),to_date('28-JUL-18','DD-MON-RR'));



CREATE TABLE RETAIL_DESC (  
    ITEM VARCHAR2(25 BYTE), 
    LOC NUMBER(10,0), 
    UNIT_RETAIL NUMBER(20,4), 
    ACTION_DATE DATE 
)  


Insert into RETAIL_DESC (ITEM,LOC,UNIT_RETAIL,ACTION_DATE) values ('13252099',473,379.97,to_date('09-JUL-18','DD-MON-RR'));
Insert into RETAIL_DESC (ITEM,LOC,UNIT_RETAIL,ACTION_DATE) values ('13252099',473,299.97,to_date('22-JUL-18','DD-MON-RR'));
Insert into RETAIL_DESC (ITEM,LOC,UNIT_RETAIL,ACTION_DATE) values ('13252099',473,0.01,to_date('19-AUG-18','DD-MON-RR'));
Insert into RETAIL_DESC (ITEM,LOC,UNIT_RETAIL,ACTION_DATE) values ('13252099',473,379.97,to_date('25-AUG-18','DD-MON-RR'));
Insert into RETAIL_DESC (ITEM,LOC,UNIT_RETAIL,ACTION_DATE) values ('13252098',470,500.18,to_date('08-JUL-18','DD-MON-RR'));
Insert into RETAIL_DESC (ITEM,LOC,UNIT_RETAIL,ACTION_DATE) values ('13252098',470,299.97,to_date('09-JUL-18','DD-MON-RR'));
Insert into RETAIL_DESC (ITEM,LOC,UNIT_RETAIL,ACTION_DATE) values ('13252098',470,0.01,to_date('19-JUL-18','DD-MON-RR'));
Insert into RETAIL_DESC (ITEM,LOC,UNIT_RETAIL,ACTION_DATE) values ('13252098',470,379.97,to_date('24-JUL-18','DD-MON-RR'));
Insert into RETAIL_DESC (ITEM,LOC,UNIT_RETAIL,ACTION_DATE) values ('13252098',470,300,to_date('24-JUL-18','DD-MON-RR'));

введите описание изображения здесь

Примечание: я использую базу данных Oracle 11g.1.Table Retail_desc содержит unit_retail (цена) для элемента для определенного местоположения.Action_date - это дата, в которую unit_retail для этого предмета обновляется до новой цены для данного конкретного местоположения.комбинация предмет / местоположение может иметь несколько action_date в зависимости от того, сколько дней цена обновляется до новых цен.

Табличная транзакция содержит дату (tran_date), в которую товар был продан из определенного места покупателю (post_date совпадает с tran_date- может игнорировать его).

я хочу знать unit_retail (цена) товара, который был продан клиенту в определенном месте.

дополнительные комментарии: 1. для каждой комбинации товара / местоположения я хочу получить розничную единицу, какую комбинацию товара / местоположения имеет во время транзакции (tran_date) 2. action_date - дата, в которую unit_retail для товара / местоположения изменяется с новой розничной торговлей.3. если единичная розничная цена изменяется несколько раз за одну дату действия, тогда выберите розничную торговлю с более низкой ценой.

Ответы [ 2 ]

0 голосов
/ 22 сентября 2018

Сначала я думаю о коррелированном подзапросе для этого:

select t.*,
       (select min(rd.unit_retail) keep (dense_rank first order by rd.acction_date desc)
        from retail_desc rd
        where rd.loc = t.location and rd.item = t.item and
              rd.action_date <= t.post_date
       ) as unit_retail
from transaction t;

Однако, может быть лучше использовать lead() и join:

select t.*, rd.unit_retail
from transaction t left join
     (select rd.*,
             lead(rd.action_date) over (partition by item, loc order by action_date) as next_action_date
      from retail_desc rd
     ) rd
     on t.location = rd.loc and t.item = rd.item and
        t.post_date >= rd.action_date and
        (t.post_date < rd.next_action_date or rd.next_action_date is null);

dense_rank()не имеет очевидной связи с этой проблемой.

0 голосов
/ 22 сентября 2018

Вам нужен подзапрос с объединением и row_number:

select item, loc, unit_retail, tran_date
from (
  select
      r.item, r.loc, r.unit_retail, t.tran_date
    , row_number() over (partition by r.item, r.loc, t.tran_date order by r.action_date desc, r.unit_retail) as rn
  from transaction t
  inner join retail_desc r on
    t.item = r.item
    and t.location = r.loc
  where t.tran_date >= r.action_date
) t
where rn = 1
order by item desc, loc desc, tran_date

Вывод данных для образца:

ITEM        LOC     UNIT_RETAIL  TRAN_DATE
13252099    473     379,97       09.07.2018 00:00:00
13252099    473     299,97       25.07.2018 00:00:00
13252098    470     299,97       09.07.2018 00:00:00
13252098    470     300          28.07.2018 00:00:00
...