2013-06-03 48 views
4

我試圖根據存儲在Oracle數據庫中的表寫出一個批處理作業計劃。從計劃表中查找工作順序?

我真的不知道從哪裏開始。

表只有兩個相關列:

JOBSTREAM  | FOLLOW_JOBSTREAM 

作業流是要運行作業流的名稱。 FOLLOW_JOBSTREAM是在作業流運行之前必須完成的作業流的名稱。在某些情況下,一個JOBSTREAM條目有幾個FOLLOW_JOBSTREAM條目。

例如:

JS001  JS028 
JS001A  JS039 
JS001B  JS001A 
JS002  JS001A 
JS002  JS001B 

有沒有一種方法排序這些使用PL/SQL?

謝謝!

+1

開始遞歸CTE!你的例子中的 –

+1

什麼jobstream會先運行? – ChrisCamp

+0

@Goat_CO感謝您的提示! Oracle CTE有什麼好的資源? – TimeBomb006

回答

2

首先,我們需要從兩個列有層次的聯繫完全作業列表:

select 
    all_jobs.job_id    as jobstream, 
    job_depends.follow_jobstream as parent_jobstream 
    from 
    (
     select jobstream job_id from job_list 
     union 
     select follow_jobstream job_id from job_list 
    ) all_jobs, 
    job_list job_depends 
    where 
    job_depends.jobstream (+) = all_jobs.job_id 

然後確定每個崗位的深度。

with full_job_list as (
    select 
    all_jobs.job_id    as jobstream, 
    job_depends.follow_jobstream as parent_jobstream 
    from 
    (
     select jobstream job_id from job_list 
     union 
     select follow_jobstream job_id from job_list 
    ) all_jobs, 
    job_list job_depends 
    where 
    job_depends.jobstream (+) = all_jobs.job_id 
) 
select 
    CONNECT_BY_ROOT jobstream   as jobstream, 
    level        as lvl, 
    CONNECT_BY_ROOT parent_jobstream  as preceding_jobstream, 
    sys_connect_by_path(jobstream, '<-') as path_illustration 
from 
    full_job_list 
connect by 
    prior parent_jobstream = jobstream 

最後根據深度安排工作。同一深度的作業可以按任意順序工作。

with full_job_list as (
    select 
    all_jobs.job_id    as jobstream, 
    job_depends.follow_jobstream as parent_jobstream 
    from 
    (
     select jobstream job_id from job_list 
     union 
     select follow_jobstream job_id from job_list 
    ) all_jobs, 
    job_list job_depends 
    where 
    job_depends.jobstream (+) = all_jobs.job_id 
) 
select 
    jobstream, 
    depth, 
    preceding_jobstream 
from (
    select distinct 
    jobstream, 
    ( 
     last_value(lvl ignore nulls) 
     over (partition by jobstream 
      order by lvl 
      rows between unbounded preceding and unbounded following 
      ) 
    ) as depth, 
    (
     last_value(preceding_jobstream ignore nulls) 
     over (partition by jobstream 
      order by lvl 
      rows between unbounded preceding and unbounded following 
      ) 
    ) as preceding_jobstream 
    from (
    select 
     CONNECT_BY_ROOT jobstream  as jobstream, 
     level       as lvl, 
     CONNECT_BY_ROOT parent_jobstream as preceding_jobstream 
    from 
     full_job_list 
    connect by 
     prior parent_jobstream = jobstream 
) 
) 
order by depth, jobstream 

SQL Fiddle

更新糾正,以獲得完整的任務列表和添加前的工作。

Update2更正了路徑方向的錯誤。

+1

如果「FOLLOW_JOBSTREAM是**作業流運行前必須完成的作業流的名稱」,則f.ex. 'JS001'必須在**'JS028'之後運行,並且在你的解決方案中它看起來完全相反(根據你提供的Fiddle)。 – Chorel

+0

@Chorel謝謝,糾錯。現在樹建立在正確的方向。 – ThinkJet

+0

哇!這難以置信。這會以正確的順序提取作業流。我所要做的就是將每個job_list引用更改爲實際的表名稱。非常感謝! – TimeBomb006

1

Hierarchical queries可以幫助你在這種情況下:

SELECT JOBSTREAM, FOLLOW_JOBSTREAM 
FROM <jobstreams> 
START WITH FOLLOW_JOBSTREAM NOT IN (SELECT JOBSTREAM 
            FROM jobstreams 
            ) 
CONNECT BY PRIOR JOBSTREAM = FOLLOW_JOBSTREAM 

SQL Fiddle

+0

不工作,因爲一個工作可以有2個父母,例如有問題的JS001A。 – ThinkJet

+0

它的工作原理 - 'JS001A'只有一個父母('JS039')。在這個例子中有兩個是'JS002',並在它們之後正確顯示。請注意,第一列的作業必須在第二列的作業之後運行。 – Chorel

+0

答案中的工作確切順序是什麼,以及如何通過結果集中的正式規則確定此順序? – ThinkJet

1

有在調度多個作業鏈接在一起的Oracle官方方法。

DBMS_Scheduler允許您根據鏈中先前步驟的退出條件定義具有依賴關係的作業鏈。它可能比本土方法更加靈活和複雜,所以我將在未來考慮遷移到它。

+0

感謝您的意見。實際的工作流/工作流程由名爲Tivoli Maestro Scheduler的程序定義/運行。我只是想用這種方法來捕捉時間表。 – TimeBomb006