Создать таблицу с диапазоном временных отметок - Oracle SQL - PullRequest
0 голосов
/ 23 апреля 2020

Я пытаюсь создать таблицу с 2 столбцами в следующем формате со всеми датами 2019 года: -

      START_TIME          END_TIME
2010-01-01 17:00:00|2019-01-02 17:00:00
2019-01-02 17:00:00|2019-01-03 17:00:00
2019-01-03 17:00:00|2019-01-04 17:00:00
...
...
2019-12-31 17:00:00|2020-01-01 17:00:00

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

CREATE TABLE s.dates_2019
(
ts_range_begin timestamp(6),
ts_range_end timestamp(6),

);


 insert into s.dates_2019 (ts_range_begin)
 select 
     to_timestamp('12/31/2018 05:00 PM', 'YYYY-MM-DD HH24:MI:SS') + n.n
 from
  (select rownum n
   from   ( select 1 just_a_column
         from   dual
         connect by level <=
                to_timestamp('12/31/2019 05:00 PM', 'YYYY-MM-DD HH24:MI:SS') 
               -  to_timestamp('12/31/2018 05:00 PM', 'YYYY-MM-DD HH24:MI:SS')  
               + 1
           ) t
  ) n
  where
       to_timestamp('12/31/2018 05:00 PM','YYYY-MM-DD HH24:MI:SS')  + n.n <=  to_timestamp('12/31/2019 05:00 PM','YYYY-MM-DD HH24:MI:SS') 

 insert into s.dates_2019 (ts_range_end)
 select 
     to_timestamp('2019-01-01 05:00 PM', 'YYYY-MM-DD HH24:MI:SS') + n.n
 from
  (select rownum n
   from   ( select 1 just_a_column
         from   dual
         connect by level <=
                to_timestamp('2020-01-01 05:00 PM', 'YYYY-MM-DD HH24:MI:SS') 
               -  to_timestamp('2019-01-01 05:00 PM', 'YYYY-MM-DD HH24:MI:SS')  
               + 1
           ) t
  ) n
  where
       to_timestamp('2019-01-01 05:00 PM','YYYY-MM-DD HH24:MI:SS')  + n.n <=  to_timestamp('2020-01-01 05:00 PM','YYYY-MM-DD HH24:MI:SS')

Ошибка: - [Error Code: 30081, SQL State: 99999] ORA-30081: invalid data type for datetime/interval arithmetic

Ответы [ 2 ]

1 голос
/ 23 апреля 2020

Я думаю, что ваша настоящая ошибка в том, что вычитание меток времени возвращает интервал, а вы используете результат как число в CONNECT BY LEVEL. Вы можете использовать метки времени как даты (вы можете найти ответы здесь полезными) или использовать интервальное выражение , чтобы получить дневной компонент между метками времени.

Но если это ваш фактический SQL, а не упрощение, я предлагаю просто использовать даты в CONNECT BY (вы все равно можете сохранять временные метки в своей таблице, если вы этого хотите) и делать что-то вроде ...

CREATE TABLE dates_2019
(
ts_range_begin timestamp(6),
ts_range_end timestamp(6)
);

insert into dates_2019 (ts_range_begin)
 select 
     to_timestamp('2018-12-31 17', 'YYYY-MM-DD HH24') + rownum
 from
     dual
 connect by level <= to_date('2019-12-31 17', 'YYYY-MM-DD HH24') - to_date('2018-12-31 17', 'YYYY-MM-DD HH24')
 ;

update dates_2019 SET ts_range_end = ts_range_begin + 1;

... который я тестировал в Oracle 18 c, но, вероятно, работает 10g.

1 голос
/ 23 апреля 2020

Как насчет этого?

SQL> alter session set nls_date_format = 'yyyy-mm-dd hh24:mi';

Session altered.

SQL> with dates as
  2    (select date '2019-01-01' + 17/24 + level - 1 datum
  3     from dual
  4     connect by level <= date '2020-01-01' - date '2019-01-01' + 1
  5    ),
  6  staend as
  7    (select datum as start_time,
  8            lead(datum) over (order by datum) as end_time
  9     from dates
 10    )
 11  select start_time,
 12         end_time
 13  from staend
 14  where end_time is not null
 15  order by start_time;

START_TIME       END_TIME
---------------- ----------------
2019-01-01 17:00 2019-01-02 17:00
2019-01-02 17:00 2019-01-03 17:00
2019-01-03 17:00 2019-01-04 17:00
2019-01-04 17:00 2019-01-05 17:00
<snip>
2019-12-30 17:00 2019-12-31 17:00
2019-12-31 17:00 2020-01-01 17:00

365 rows selected.

SQL>

Если вы хотите вставить даты в таблицу, вам на самом деле не нужно timestamp - date.

SQL> create table dates_2019
  2    (ts_range_begin date,
  3     ts_range_end   date
  4    );

Table created.

SQL> insert into dates_2019 (ts_range_begin, ts_range_end)
  2  with dates as
  3    (select date '2019-01-01' + 17/24 + level - 1 datum
  4     from dual
  5     connect by level <= date '2020-01-01' - date '2019-01-01' + 1
  6    ),
  7  staend as
  8    (select datum as start_time,
  9            lead(datum) over (order by datum) as end_time
 10     from dates
 11    )
 12  select start_time,
 13         end_time
 14  from staend
 15  where end_time is not null
 16  order by start_time;

365 rows created.

SQL>

Если вы хотите агрегировать выходные, рассмотрите возможность использования offset в функции lead analyti c. Это смещение зависит от названия дня (пятница). Также удалите выходные дни из набора результатов (строка № 21, where day not in ('sat', 'sun')).

SQL> insert into dates_2019 (ts_range_begin, ts_range_end)
  2  with dates as
  3    (select date '2019-01-01' + 17/24 + level - 1 datum,
  4            --
  5            to_char(date '2019-01-01' + 17/24 + level - 1,
  6                    'fmdy', 'nls_date_language = english') day
  7     from dual
  8     connect by level <= date '2020-01-01' - date '2019-01-01' + 1
  9    ),
 10  staend as
 11    (select datum as start_time,
 12            day,
 13            lead(datum, case when day = 'fri' then 3
 14                             else 1
 15                        end) over (order by datum) as end_time
 16     from dates
 17    )
 18  select start_time,
 19         end_time
 20  from staend
 21  where day not in ('sat', 'sun')
 22    and end_time is not null;

261 rows created.

SQL> select * from dates_2019 order by ts_range_begin;

TS_RANGE_BEGIN   TS_RANGE_END
---------------- ----------------
2019-01-01 17:00 2019-01-02 17:00
2019-01-02 17:00 2019-01-03 17:00
2019-01-03 17:00 2019-01-04 17:00
2019-01-04 17:00 2019-01-07 17:00     --> aggregated
2019-01-07 17:00 2019-01-08 17:00
2019-01-08 17:00 2019-01-09 17:00
2019-01-09 17:00 2019-01-10 17:00
2019-01-10 17:00 2019-01-11 17:00
2019-01-11 17:00 2019-01-14 17:00     --> aggregated
2019-01-14 17:00 2019-01-15 17:00
2019-01-15 17:00 2019-01-16 17:00
<snip>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...