连接和级别 - 小时间隔

时间:2016-01-12 12:38:32

标签: sql oracle

我有以下数据:

ID  SESSION START_DATE          END_DATE
1   A       01/01/2016 22:35    02/01/2016 02:35
1   B       02/01/2016 02:35    02/01/2016 04:45
2   A       01/01/2016 00:00    01/01/2016 02:00
2   B       01/01/2016 02:00    01/01/2016 03:30

我需要像这样回来:

ID  SESSION START_DATE          END_DATE
1   A       01/01/2016 22:35    01/01/2016 22:59
1   A       01/01/2016 23:00    01/01/2016 23:59
1   A       02/01/2016 00:00    02/01/2016 00:59
1   A       02/01/2016 01:00    02/01/2016 01:59
1   A       02/01/2016 02:00    02/01/2016 02:35
1   B       02/01/2016 02:35    02/01/2016 02:59
1   B       02/01/2016 03:00    02/01/2016 03:59
1   B       02/01/2016 04:00    02/01/2016 04:45
2   A       01/01/2016 00:00    01/01/2016 00:59
2   A   ... 

任何帮助?

3 个答案:

答案 0 :(得分:0)

这是一个解决方案,你只需要一点小时提取:

create table connect_by_hour_test(id number, sess varchar2(1), start_date date, end_date date);

insert into connect_by_hour_test (id, sess, start_date, end_date) values (1, 'A', to_date('01/01/2016 22:30', 'dd/mm/yyyy hh24:mi'), to_date('02/01/2016 02:35', 'dd/mm/yyyy hh24:mi'));
insert into connect_by_hour_test (id, sess, start_date, end_date) values (1, 'B', to_date('02/01/2016 02:35', 'dd/mm/yyyy hh24:mi'), to_date('02/01/2016 04:45', 'dd/mm/yyyy hh24:mi'));
insert into connect_by_hour_test (id, sess, start_date, end_date) values (2, 'A', to_date('01/01/2016 00:00', 'dd/mm/yyyy hh24:mi'), to_date('01/01/2016 02:00', 'dd/mm/yyyy hh24:mi'));
insert into connect_by_hour_test (id, sess, start_date, end_date) values (2, 'B', to_date('01/01/2016 02:00', 'dd/mm/yyyy hh24:mi'), to_date('01/01/2016 03:30', 'dd/mm/yyyy hh24:mi'));

commit;

with max_level as (
select id, sess, ceil((end_date - start_date) / (1/24)) as val from connect_by_hour_test ) -- get the max number of iterations for each (id, sess) pair
select distinct 
    id, 
    sess,
    decode(level, 1, to_char(start_date, 'dd/mm/yyyy hh24:mi'), to_char(trunc(start_date, 'hh24') + 1/24 * level - 1/24, 'dd/mm/yyyy hh24:mi')) start_date, -- if first iteration in pair show the start_date, otherwise show the start date, plus the number of hours for the current iteration(first iteration - 1 hour, 2nd iteration - two hours, etc) minus one minute
    decode(level, (select val from max_level ml where ml.id = src.id and ml.sess = src.sess), to_char(end_date, 'dd/mm/yyyy hh24:mi'), to_char(trunc(start_date, 'hh24') + 1/24 * level - 1/24/60, 'dd/mm/yyyy hh24:mi')) end_date -- if last iteration show end_date, otherwise show value from previous iteration plus one minute
  from 
    connect_by_hour_test src
  connect by 
    trunc(start_date, 'hh24') + 1/24 * (level - 1) <= end_date order by 1,2;

编辑:在反馈后进行更正,将步骤添加到级别-1,将max_level计算为ceil,而不是截断,结束时为end_date - start_date

答案 1 :(得分:0)

您可以尝试这样的事情:

SELECT DISTINCT session,
              id,
              st,
              end
FROM (    SELECT DECODE(LEVEL, 1, start_date, TRUNC(start_date, 'HH') + (LEVEL - 1) / 24) st,
                 PRIOR id p_id,
                 id,
                 PRIOR session p_session,
                 session,
                 LEAST(end_date, TRUNC(start_date, 'HH') + (LEVEL) / 24 - 1 / 24 / 60) end
            FROM tab
      CONNECT BY LEVEL <= EXTRACT(HOUR FROM end_date - start_date) + 1)
WHERE    (    p_id = id
          AND p_session = session)
      OR (p_id IS NULL)

我想避免使用DISTINCT,但找不到办法,希望别人可以提供更好的解决方案

答案 2 :(得分:0)

选择级别, NR_ATENDIMENTO, CD_SETOR_ATENDIMENTO, 最大的(DT_ENTRADA_UNIDADE,trunc(DT_ENTRADA_UNIDADE +(level-1)/ 24,&#39; hh24&#39;)DT_ENTRADA_UNIDADE, to_char(trunc(DT_ENTRADA_UNIDADE,&#39; hh24&#39;)+ 1/24 *级别 - 1/24/60,&#39; dd / mm / yyyy hh24:mi:ss&#39;)DT_SAIDA_UNIDADE 从 ( 选择         CD_SETOR_ATENDIMENTO,
        NR_SEQ_INTERNO,         DT_ENTRADA_UNIDADE,         nvl(DT_SAIDA_UNIDADE,sysdate)DT_SAIDA_UNIDADE,         NR_ATENDIMENTO 来自ATEND_PACIENTE_UNIDADE OBTER_TIPO_UNIDADE_ATEND(NR_ATENDIMENTO,NR_SEQ_INTERNO,IE_PASSAGEM_SETOR)不在(&#39; S&#39;) AND nr_atendimento = 831838 由NR_ATENDIMENTO订购, CD_SETOR_ATENDIMENTO, DT_ENTRADA_UNIDADE DESC ) 在哪里1 = 1 CONNECT BY ROWID = PRIOR ROWID 和trunc(DT_ENTRADA_UNIDADE,&#39; hh24&#39;)+ 1/24 *(level-1)&lt; = nvl(DT_SAIDA_UNIDADE,sysdate) AND PRIOR SYS_GUID()不是NULL 按2,3,4排序;