расшифровать день и сравнить с колонкой - PullRequest
0 голосов
/ 15 марта 2019

У меня есть столбцы:

1.: delivery_date столбец. Возвращает день недели, например:

1  --monday
2  --tuesday
3  --wednesday
4  --thursday
5  --friday

2 .: date столбец .. Возвращает дату получения - это обычный столбец даты - пример: 25.03.2019 (format DD.MM.YYYY)

Но, наша система автоматически сравнивает и устанавливает date с ближайшим delivery_date.

Пример:

у партнера delivery_date каждую неделю в четверг и во вторник. [Так 4 и 2]. Он хочет забрать товар в пятницу. В настоящее время наша система меняет date на четверг. Но я хочу следующий date, который является вторником - , и я хочу декодировать его до даты (формат ДД.ММ.ГГГГ)

Выходные данные будут такими:

--if pick up date: 22.03.2019 (friday)
--partner has delivery_date: 4,2(thursday, tuesday)

I want to get: 26.03.2019 --as output

Я могу сравнить столбцы ... это не проблема ... Но как я могу декодировать дату "фактического получения"?

Как я могу это сделать?

1 Ответ

1 голос
/ 17 марта 2019

Для решения этой проблемы может быть полезно создать таблицу «календарь» - сделайте ее достаточно большой (!), Которая впоследствии может быть использована для уплотнения ваших данных (см. Комментарии в коде ниже).Для тестирования давайте используем следующие таблицы (Oracle 12c, 18c):

Таблица CAL_

create table cal_
as
select sysdate + level date_
, to_char( sysdate + level, 'Day' ) dname_
, to_char( sysdate + level, 'D' )   dnumber_
from dual
connect by level <= 31 ;  -- number should be big enough to cover the lifetime of your system

SQL> select * from cal_ ;
DATE_      DNAME_     DNUMBER_  
17-MAR-19  Sunday     7         
18-MAR-19  Monday     1         
19-MAR-19  Tuesday    2         
20-MAR-19  Wednesday  3         
21-MAR-19  Thursday   4  
...
12-APR-19  Friday     5         
13-APR-19  Saturday   6         
14-APR-19  Sunday     7         
15-APR-19  Monday     1         
16-APR-19  Tuesday    2  

Таблица DELIVERYDAYS

create table deliverydays ( partner, deliveryday, dayofweek )
as
select
  mod( level, 3 ) + 1 
, mod( level, 5 ) + 1
, to_char( sysdate + ( mod( level, 5 ) + 2 ), 'Day' )
from dual
connect by level <= 10 ;

-- partner 4 delivers on Tue and Thu (same days as in the question)
insert into deliverydays ( partner, deliveryday, dayofweek )
values ( 4, 2, 'Tuesday' ) ;
insert into deliverydays ( partner, deliveryday, dayofweek )
values ( 4, 4, 'Thursday' ) ;

SQL> select * from deliverydays order by partner, deliveryday ;
PARTNER  DELIVERYDAY  DAYOFWEEK  
1        2            Tuesday    
1        4            Thursday   
1        5            Friday     
2        1            Monday     
2        2            Tuesday    
2        3            Wednesday  
2        5            Friday     
3        1            Monday     
3        3            Wednesday  
3        4            Thursday   
4        2            Tuesday    
4        4            Thursday   

12 rows selected. 

Вы можете DENSIFY ваши данные, как это.Обратите внимание, что промежутки между днями доставки становятся видимыми.(Имена столбцов с последними подчеркиваниями: из таблицы CAL_).

select 
  partner, deliveryday , dayofweek 
, date_, dname_, dnumber_
from deliverydays D partition by ( partner )
  right join cal_ C on D.deliveryday = C.dnumber_
where partner = 4
order by date_ ;

PARTNER  DELIVERYDAY  DAYOFWEEK  DATE_      DNAME_     DNUMBER_  
4        NULL         NULL       17-MAR-19  Sunday     7         
4        NULL         NULL       18-MAR-19  Monday     1         
4        2            Tuesday    19-MAR-19  Tuesday    2         
4        NULL         NULL       20-MAR-19  Wednesday  3         
4        4            Thursday   21-MAR-19  Thursday   4         
4        NULL         NULL       22-MAR-19  Friday     5         
4        NULL         NULL       23-MAR-19  Saturday   6         
4        NULL         NULL       24-MAR-19  Sunday     7         
4        NULL         NULL       25-MAR-19  Monday     1         
4        2            Tuesday    26-MAR-19  Tuesday    2         
4        NULL         NULL       27-MAR-19  Wednesday  3         
4        4            Thursday   28-MAR-19  Thursday   4  
...
-- 31 rows selected

В качестве следующего шага вы можете использовать функцию LEAD (), чтобы найти «следующие» даты доставки, а затем рассчитать суммудней между «получением» и доставкой, и форматируйте даты по мере необходимости.(См. «Закомментированную» версию запроса здесь .)

select pid, dday, next_dday, date_, dname_, dnumber_
, case 
    when dnumber_ > next_dday then ( 7 - dnumber_ + next_dday ) -- next week
    else next_dday - dnumber_
  end ddiff_
, case
    when dnumber_ > next_dday then
      to_char( date_ + ( 7 - dnumber_ + next_dday ), 'DD.MM.YYYY' )
    else 
      to_char( date_ + ( next_dday - dnumber_ ), 'DD.MM.YYYY' )
  end delivered_on 
from (
  select  
    partner as pid, deliveryday as dday
  , lead( deliveryday ) ignore nulls over ( order by date_ ) as next_dday
  , dayofweek 
  , date_, dname_, dnumber_
  from deliverydays D partition by ( partner )
    right join cal_ C on D.deliveryday = C.dnumber_
  where partner = 4 -- partner id
)
where to_char( date_, 'DD.MM.YYYY' ) = '22.03.2019' -- "pick up" date
order by date_  ;

Результат

PID  DDAY  NEXT_DDAY  DATE_      DNAME_     DNUMBER_  DDIFF_  DELIVERED_ON  
4    NULL  2          22-MAR-19  Friday     5         4       26.03.2019 

Без использования внешнего предложения WHEREмы получаем ..

PID  DDAY  NEXT_DDAY  DATE_      DNAME_     DNUMBER_  DDIFF_  DELIVERED_ON  
4    NULL  2          17-MAR-19  Sunday     7         2       19.03.2019    
4    NULL  2          18-MAR-19  Monday     1         1       19.03.2019    
4    2     4          19-MAR-19  Tuesday    2         2       21.03.2019    
4    NULL  4          20-MAR-19  Wednesday  3         1       21.03.2019    
4    4     2          21-MAR-19  Thursday   4         5       26.03.2019    
4    NULL  2          22-MAR-19  Friday     5         4       26.03.2019    
4    NULL  2          23-MAR-19  Saturday   6         3       26.03.2019    
4    NULL  2          24-MAR-19  Sunday     7         2       26.03.2019    
4    NULL  2          25-MAR-19  Monday     1         1       26.03.2019    
4    2     4          26-MAR-19  Tuesday    2         2       28.03.2019    
4    NULL  4          27-MAR-19  Wednesday  3         1       28.03.2019    
4    4     2          28-MAR-19  Thursday   4         5       02.04.2019 
...
-- 31 rows selected
...