2016-08-23 4 views
0

У меня есть таблица А, как показано нижеOracle - Назначение правильного Дата из набора

REGID | PKG_DESC | EVENT_DATE | IS_CON | IS_REN 
----------------------------------------------------- 
1234 | cc  | 27-MAR-14  | 0  | 0 
1234 | cc  | 27-JUN-14  | 1  | 0 
1234 | GUI  | 27-MAR-14  | 0  | 0 
1234 | GUI  | 27-JUN-14  | 1  | 0 
1234 | GUI  | 27-SEPT-14 | 0  | 1 
1234 | GUI  | 27-SEPT-15 | 0  | 1 
1234 | REMOTE | 27-MAR-14  | 0  | 0 
1234 | REMOTE | 27-JUN-14  | 1  | 0 
1234 | REMOTE | 27-SEPT-14 | 0  | 1 
2431 | cc  | 27-MAR-14  | 0  | 0 
2431 | cc  | 27-JUN-14  | 1  | 0 

У меня есть запрос, как показано ниже

select a.reg_id, b.sess_start_dt, 
case when TRUNC(A.EVENT_DATE) - B.SESS_START_DT BETWEEN 0-30 THEN 'DAYS 0_30' 
WHEN TRUNC(A.EVENT_DATE) - B.SESS_START_DT BETWEEN 31-60 THEN 'DAYS 31-60' 
    from tab a inner join tab b on a.reg_id = b.reg_id and a.is_ren = 1 

union 

select a.reg_id, b.sess_start_dt, 
case when TRUNC(A.EVENT_DATE) - B.SESS_START_DT BETWEEN 0-30 THEN 'DAYS 0_30' 
WHEN TRUNC(A.EVENT_DATE) - B.SESS_START_DT BETWEEN 31-60 THEN 'DAYS 31-60' 
    from tab a inner join tab b on a.reg_id = b.reg_id and a.is_con = 1 

Tab B содержит все использование для каждого reg_id там будет быть 100 из записей .. Пример немногие

REGID | SESS_START_DT 
    1234 | 27-Jan-14 
    1234 | 20-MAR-12 
    1234 | 27-MAR-12 
    1234 | 01-sept-14 
    1234 | 07-sept-14 
    1234 | 29-JUL-14 
    1234 | 03-AUG-14 
    1234 | 27-MAR-13 
    1234 | 27-MAR-12 
    1234 | 27-MAR-12 
    1234 | 27-MAR-12 
    1234 | 27-MAR-12 
    1234 | 27-MAR-12 
    1234 | 27-MAR-12 
    2431 | 20-JUN-14 

выше запрос должен быть исправлен так, как,

1) If the REG_ID is having at least one is_ren = 1 then that subscription should be considered as renewal subscription and needs to get the 30 days and 60 days usage from table B from his is_ren = 1 event_date. (for REGID 1234 only is_ren query should execute)

2) If multiple IS_REN = 1 are existing for each REGID then the usage needs to be taken 30 days and 60 days from table B with the MIN(event_date). in this case the usage should be taken from 27-SEPT-14 instead of 27-SEPT-15

3) If there is no IS_REN = 1 and there is IS_CON = 1 then it's considered as conversion and usage should be taken before 60 days from the converted date (for REGID 2431, usage needs to get 60 days back from 27-JUN-14{this is my event_date in the query})

O/P должно быть как

REGID  | EVENT_DATE  | DAYS 0_30 | DAYS 31-60 | CODE 
1234  | 27-SEPT-14  | 2    | 2   | REN 
2431  | 27-JUL-14  | 1    | 0   | CON 
+0

Можете ли вы определить такие термины, как «получить 30 дней и 60 дней использования из таблицы B» и «использование необходимо получить 60 дней назад от ...» - это не условия базы данных (по крайней мере, не термины Oracle). Демонстрация вывода проб может помочь. – mathguy

+0

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

+0

@mathguy - Если вы помните, что вы предоставили мне решения за эти несколько дней назад. http://stackoverflow.com/questions/38318535/oracle-sql-how-to-get-counts-based-up-on-dates-into-multiple-columns-in-oracle/38318785#38318785 .. Там у нас есть использовал Sysdate, и здесь нам нужно использовать event_date. Мне нужно определить, какой event_date использовать, и все это мой вопрос: – beckham

ответ

1

Если мои предположения в мой комментарий правильно, это может быть то, что вам нужно. Обратите внимание на предложение order by в row_number() - сначала строки с is_ren = 1, затем строки с is_ren = 0 и is_con = 1, а затем все остальные строки и в каждом групповом порядке на event_date по возрастанию. Таким образом, верхняя строка (rn = 1), которая является единственной, которую я использую во внешнем запросе, будет иметь is_ren = 1 с самой ранней возможной датой, или если нет is_ren = 1, то строка с is_con = 1 и самая ранняя дата, или только самое раннее Дата. (В последнем случае CODE будет нулевым: это означает, что не было is_ren = 1 и не is_con = 1 для этого regid

Не знаю, почему у вас есть 27-JUL-14 на выходе для regid = 2431, который должен быть 27-JUN-14 Кроме того, есть.. нет четырехбуквенных месяцев в Oracle («SEPT»). На выходе отображаются даты с использованием параметров моего сеанса, и если вам нужно отформатировать даты, используйте to_date(event_date, .....) с желаемой моделью формата даты. Кроме того, поскольку данные, которые вы предоставили, без какого-либо компонента времени), я не урезал ничего, вам может понадобиться, если ваши реальные данные имеют компоненты времени суток.

with 
    table_a (regid, pkg_desc, event_date, is_con, is_ren) as (
     select 1234, 'cc' , to_date ('27-MAR-14', 'dd-MON-rr'), 0, 0 from dual union all 
     select 1234, 'cc' , to_date ('27-JUN-14', 'dd-MON-rr'), 1, 0 from dual union all 
     select 1234, 'GUI' , to_date ('27-MAR-14', 'dd-MON-rr'), 0, 0 from dual union all 
     select 1234, 'GUI' , to_date ('27-JUN-14', 'dd-MON-rr'), 1, 0 from dual union all 
     select 1234, 'GUI' , to_date ('27-SEP-14', 'dd-MON-rr'), 0, 1 from dual union all 
     select 1234, 'GUI' , to_date ('27-SEP-15', 'dd-MON-rr'), 0, 1 from dual union all 
     select 1234, 'REMOTE', to_date ('27-MAR-14', 'dd-MON-rr'), 0, 0 from dual union all 
     select 1234, 'REMOTE', to_date ('27-JUN-14', 'dd-MON-rr'), 1, 0 from dual union all 
     select 1234, 'REMOTE', to_date ('27-SEP-14', 'dd-MON-rr'), 0, 1 from dual union all 
     select 2431, 'cc' , to_date ('27-MAR-14', 'dd-MON-rr'), 0, 0 from dual union all 
     select 2431, 'cc' , to_date ('27-JUN-14', 'dd-MON-rr'), 1, 0 from dual 
    ), 
    table_b (regid, sess_start_dt) as (
     select 1234, to_date ('27-JAN-14', 'dd-MON-rr') from dual union all 
     select 1234, to_date ('20-MAR-12', 'dd-MON-rr') from dual union all 
     select 1234, to_date ('27-MAR-12', 'dd-MON-rr') from dual union all 
     select 1234, to_date ('01-SEP-14', 'dd-MON-rr') from dual union all 
     select 1234, to_date ('07-SEP-14', 'dd-MON-rr') from dual union all 
     select 1234, to_date ('29-JUL-14', 'dd-MON-rr') from dual union all 
     select 1234, to_date ('03-AUG-14', 'dd-MON-rr') from dual union all 
     select 1234, to_date ('27-MAR-13', 'dd-MON-rr') from dual union all 
     select 1234, to_date ('27-MAR-12', 'dd-MON-rr') from dual union all 
     select 1234, to_date ('27-MAR-12', 'dd-MON-rr') from dual union all 
     select 1234, to_date ('27-MAR-12', 'dd-MON-rr') from dual union all 
     select 1234, to_date ('27-MAR-12', 'dd-MON-rr') from dual union all 
     select 1234, to_date ('27-MAR-12', 'dd-MON-rr') from dual union all 
     select 1234, to_date ('27-MAR-12', 'dd-MON-rr') from dual union all 
     select 2431, to_date ('20-JUN-14', 'dd-MON-rr') from dual 
    ), 
    prep (regid, event_date, code, rn) as (
     select regid, event_date, 
       case when is_ren = 1 then 'REN' when is_con = 1 then 'CON' else null end, 
       row_number() over (partition by regid 
           order by case when is_ren = 1 then 0 
               when is_con = 1 then 1 else 2 end, 
           event_date) 
     from table_a 
    ) 
select p.regid, p.event_date, 
     count(case when b.sess_start_dt between p.event_date - 30 and p.event_date 
                  then 1 end) as days_0_30, 
     count(case when b.sess_start_dt between p.event_date - 60 and p.event_date - 31 
                  then 1 end) as days_31_60, 
     p.code 
from prep p inner join table_b b on p.regid = b.regid 
where rn = 1 
group by p.regid, p.event_date, p.code 
; 

Выход:

 REGID EVENT_DATE   DAYS_0_30 DAYS_31_60 COD 
---------- ------------------- ---------- ---------- --- 
     1234 2014-09-27 00:00:00   2   2 REN 
     2431 2014-06-27 00:00:00   1   0 CON 
+0

Спасибо за решение. Это работает. Есть ли способ разделить этот запрос на 2 части: один для Renewal и один для Conversion каждый и сделать объединение после этого? – beckham

+1

Да, и на самом деле проще писать, но менее эффективно. Вы бы вдвое увеличили объем работы, чтобы получить два отдельных набора результатов, а затем немного больше, чтобы «объединить» их. Кроме того, часть 'CON' будет сложной, потому что вам нужно будет игнорировать' regid', которые имеют 'is_ren = 1'; это дополнительная работа. Какая версия Oracle у вас есть? В Oracle 12 существует 'fetch first', который может помочь удалить структуру запроса в подзапросе - внешний запрос с помощью' row_number() '. – mathguy

+0

Я использую Oracle 11i. У меня нет проблем с использованием вышеуказанного запроса, но у меня есть одна небольшая проблема. На самом деле причина, по которой я спросил, в реальных данных у меня есть event_date, исходящий из двух разных столбцов. for is_con, event_date исходит из столбца is_con_event_date и для is_ren, event_date исходит из столбца is_ren_event_date. – beckham

Смежные вопросы