Помогите с Oracle SQL для планирования встреч - PullRequest
0 голосов
/ 22 июля 2011

У меня есть таблица встреч со следующей информацией:

id
agent_id
starts_at
ends_at
...

и с учетом графика работы агентов, начинающегося в 9:00 и заканчивающегося в 18:00 (18:00)

ипри назначении встречи, запланированной между 10:00 и 11:00 утра 2011-01-01

, можно ли разделить его расписание на кратные 30 минут

и получить следующий результат, используя SQLв Oracle:

date, slotnum, agent_id, starts_at, ends_at, appointment_id
2011-01-01, 1, 1, 09:00, 09:30, (null)
2011-01-01, 2, 1, 09:30, 10:00, (null)
2011-01-01, 3, 1, 10:00, 10:30, 1
2011-01-01, 4, 1, 10:30, 11:00, 1
2011-01-01, 5, 1, 11:00, 11:30, (null)
...
...
2011-01-01,, 18, 1, 17:30, 18:00, (null)

Заранее спасибо.

Ответы [ 3 ]

2 голосов
/ 22 июля 2011

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

create table t_agent
(id   number(9),
 agent_id  number(9),
 starts_at timestamp,
 ends_at   timestamp);

 insert into t_agent values (1,100, timestamp'2011-01-01 09:00:00.0 AMERICA/CHICAGO',timestamp'2011-01-01 18:00:00.0 AMERICA/CHICAGO');

 create table t_appointment
 (id               number(9),
  agent_id         number(9),
  start_time       timestamp,
  end_time         timestamp);

insert into t_appointment values (1,100, timestamp'2011-01-01 10:00:00.0 AMERICA/CHICAGO',timestamp'2011-01-01 11:00:00.0 AMERICA/CHICAGO');

with agent_hours as
  (select extract(hour from ends_at) end_time, 
          extract(hour from starts_at) start_time,
          to_char(trunc(starts_at)) appointment_date,
          starts_at,
          ends_at,
          agent_id
   from   t_agent 
   where agent_id=100)
   select slots.appointment_date,
          slots.slotnum,
          slots.starttime,
          slots.endtime,
          case when app.start_time >= slots.full_starttime and app.start_time < slots.full_endtime 
              or        
              app.end_time > slots.full_starttime and app.end_time <= slots.full_endtime 
    then app.id else null end app_id
     from   t_appointment app,
           (select agent_hours.appointment_date,
            rownum slotnum,
            agent_hours.agent_id,
            to_char((trunc(starts_at) + (.5/24) * agent_hours.start_time * 2) + ((rownum -1) * .5/24),' HH24:mi') starttime,
            to_char((trunc(starts_at) + (.5/24) * agent_hours.start_time * 2) + (rownum  * .5/24),'HH24:mi') endtime,
            to_timestamp(to_char(((trunc(starts_at) + (.5/24) * agent_hours.start_time * 2) + ((rownum -1) * .5/24)),'DD-MON-YYYY HH24:MI:SS'),'DD-MON-YYYY HH24:MI:SS') full_starttime,
            to_timestamp(to_char(((trunc(starts_at) + (.5/24) * agent_hours.start_time * 2) + (rownum  * .5/24)),'DD-MON-YYYY HH24:MI:SS'),'DD-MON-YYYY HH24:MI:SS') full_endtime,
            starts_at,
            ends_at
     from   agent_hours,
            ( select rownum
              from   all_objects
              where  rownum <= (select end_time - start_time from agent_hours)*2) ) slots
where slots.agent_id = app.agent_id(+);
0 голосов
/ 22 июля 2011

Попробуйте это (не проверено):

WITH time_slots AS
(
SELECT  b.starts ,
    b.starts + (rownum -1) * 0.5/24 starts_at,
    b.starts + (rownum) * 0.5/24 ends_at,
    rownum AS slotnum 
  FROM  ALL_OBJECTS a,
        (
         SELECT TRUNC(sysdate) + 9/24 AS starts --Can have the actual date you are looking for instead of SYSDATE
            FROM DUAL
        ) b
)
SELECT a.starts AS "DATE",
    a.slotnum,
    b.agent_id,
    TO_CHAR(a.starts_at, 'HH24:MI') AS starts_at,
    TO_CHAR(a.ends_at, 'HH24:MI') AS ends_at,
    b.id AS appointment_id
  FROM time_slots a LEFT JOIN appointments b
     ON (b.starts_at >= a.starts_at AND b.starts_at <= a.ends_at) OR
            (b.ends_at >= a.starts_at AND b.starts_at <= a.ends_at) 
0 голосов
/ 22 июля 2011

Да, это возможно. Вы оставляете много деталей неуказанными Я предполагаю, что у вас также есть таблица агентов (agent_id, start_hour, end_hour) с полями часа, являющимися целыми числами от 0 до 24. (Это означает, что рабочий день данного агента не меняется в разные дни.) Я также предполагаю, что пользователь, вводящий запрос, будет являться agent_id и днем, на который должно быть просмотрено расписание, последнее будет представлено как DATE.

Я не могу проверить это прямо сейчас, но я думаю, что это, по сути, будет делать то, что вы хотите:

with agent_workday as (
  select agent_id,
         :date + start_hour/24 agent_start_time,
         :date + end_hour/24 agent_end_time
    from agents
    where agent_id = :agent
), agent_slots as (
  select agent_id,
         level slotnum,
         agent_start_time + (level-1)/48 slot_start,
         agent_start_time + level/48 slot_end
    from agent_workday
    connect by level <= (agent_end_time-agent_start_time)*48
)
select :date, slotnum, agent_slots.agent_id,
       TO_CHAR(slot_start, 'HH24:MI'), TO_CHAR(slot_end, 'HH24:MI'),
       appointment_id
  from agent_slots left join appointments
       on appointments.agent_id = agent_slots.agent_id
       and agent_slots.block_start >= appointments.starts_at
       and agent_slots.block_end <= appointments.ends_at
  order by slotnum
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...