2011-07-22 26 views
0

我有如下信息的預約表:幫助與Oracle SQL任命調度

id 
agent_id 
starts_at 
ends_at 
... 

,並給予代理商安排在上午9:00開始,在6:00 PM(18:00)

結束

並給予預定的10:00和11:00 AM在2011-01-01

之間預約纔有可能在30分鐘

並獲得牛逼的倍數來劃分他的日程安排他下面的結果在Oracle中使用SQL:

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) 

在此先感謝。

+0

你能提供Starts_AT和Ends_AT的數據類型? – Chandu

+0

starts_at和ends_at是時間戳; id和agent_id是號碼 – Dharam

回答

2

我學到了在做這項工作時我自己做了幾件事。希望這給你一個這樣做的方法的想法。我的例子在每個表中的記錄,因此有更多的記錄,你可能需要調整它的性能...

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

完美並且謝謝。我絕對可以將其擴展到複雜的商業模式。什麼是最好的方式來擴大這個允許不均勻結束的時間表?我的意思是,如果代理程序時間表從上午09:00開始,但在下午05:15(17:00)結束,我不希望這些插槽超出時間表結束時間。 slots.agent_id = app.gent_id(+)中的+是什麼用途?無論是否得到相同的結果?再次感謝。 – Dharam

+0

slots.agent_id = app.agent_id(+)是外連接。即使沒有代理人的約會,這總是會返回插槽信息。 –

0

是的,這是可能的。你留下很多未詳細說明的細節。我假設你也有一個代理表(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 
+0

我不得不離開實際細節的原因是,爲了獲得代理程序時間表,我必須加入4個表格並將約會代理人與約會聯繫在一起,再加上4個表格。感謝您給予它一個鏡頭,即使是最小的細節。 – Dharam

0

試試這個(未測試):

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

我得到的sql命令沒有正確結束 – Dharam

+0

修復了錯字..現在就試試吧.... – Chandu

+0

我仍然沒有正確結束sql命令,當我在SQL Developer中最後一行運行這個 – Dharam