2010-05-27 54 views
4

我需要一個oracle查詢的幫助。混合在一起通過連接,內部連接和總結與Oracle

這裏是我的設置:

我有2個表分別被稱爲「任務」和「時間表」 「任務」表是遞歸的,這樣每個任務可以有多個子任務。每個時間表都與一個任務相關聯(不一定是「根」任務),幷包含在其上工作的小時數。

實施例:

任務

ID:1 |名稱:任務A | parent_id:NULL

id:2 |名稱:任務A1 | parent_id:1

id:3 |名稱:任務A1.1 | parent_id:2

id:4 |名稱:任務B | parent_id:NULL

id:5 |名稱:任務B1 | parent_id:4

次表

id:1 | task_id:1 |小時:1

id:2 | task_id:2 |小時:3

id:3 | task_id:3 |小時:1

id:5 | task_id:5 |時間:1 ...

我想做的事:

我想要一個查詢,將返回一個「任務層次」工作的所有時間的總和。如果我們看一下前面的例子,這意味着我想得到以下結果:

任務A - 5小時|任務B - 1小時(S)

起初我想這

SELECT TaskName, Sum(Hours) "TotalHours" 
FROM (
    SELECT replace(sys_connect_by_path(decode(level, 1, t.name), '~'), '~') As TaskName, 
    ts.hours as hours 
    FROM tasks t INNER JOIN timesheets ts ON t.id=ts.task_id 
    START WITH PARENTOID=-1 
    CONNECT BY PRIOR t.id = t.parent_id 
    ) 
GROUP BY TaskName Having Sum(Hours) > 0 ORDER BY TaskName 

它幾乎工作。唯一的問題是,如果沒有根任務的時間表,它將跳過整個時間表......但是可能有子時間表的時間表,而這正是在任務B1中發生的情況。我知道這是造成我的問題的「內部連接」部分,但我不知道我該如何擺脫它。

任何想法如何解決這個問題?

謝謝

+0

我認爲,如果你顛倒表的順序,並使用左外連接,你會得到任務,即使沒有時間片上,從而*威力*工作...也許? – FrustratedWithFormsDesigner 2010-05-27 15:04:27

+0

感謝您的幫助。在我的情況下進行左連接會導致一些主要的性能問題......即使表格索引良好,並且所有表格都是如此。 – 2010-05-27 15:30:47

回答

3

會這樣的工作?我遇到過類似於你的情況,我只是從分層查詢中刪除了連接,並在以後才應用它,以避免丟失行。

SELECT TaskName, Sum(ts.hours) "TotalHours" 
FROM (
    SELECT replace(sys_connect_by_path(decode(level, 1, t.name), '~'), '~') As TaskName, t.id 
    FROM tasks t 
    START WITH PARENTOID=-1 
    CONNECT BY PRIOR t.id = t.parent_id 
    ) tasks 
INNER JOIN timesheets ts ON tasks.id=ts.task_id 
GROUP BY TaskName Having Sum(ts.hours) > 0 ORDER BY TaskName 
+0

非常感謝!我認爲這是在做詭計。還有一些測試要做,我會將其標記爲正式答案。 – 2010-05-27 15:29:17

0

如果使用左外連接,而不是正常的加入,您可能會收到輸出。

SELECT TaskName, Sum(Hours) "TotalHours" 
FROM ( 
    SELECT replace(sys_connect_by_path(decode(level, 1, t.name), '~'), '~') As TaskName, 
    ts.hours as hours 
    FROM tasks t,timesheets ts where t.id=ts.task_id(+) 
    START WITH PARENTOID=-1 
    CONNECT BY PRIOR t.id = t.parent_id 
    ) 
GROUP BY TaskName Having Sum(Hours) > 0 ORDER BY TaskName 
+0

我想他也必須扭轉表格的順序,因爲他想要沒有相應時間表的任務。目前,如果他更改爲左外,他會得到沒有相應任務的時間表。 – FrustratedWithFormsDesigner 2010-05-27 15:08:48

+0

FrustratedWithFormsDesigner:你是對的,或者他也可以使用右外連接 – Bharat 2010-05-27 15:13:36

1

你試過嗎?

SELECT TaskName, Sum(Hours) "TotalHours" 
FROM (
    SELECT replace(sys_connect_by_path(decode(level, 1, t.name), '~'), '~') As TaskName, 
    ts.hours as hours 
    FROM timesheets ts LEFT OUTER JOIN tasks t ON t.id=ts.task_id 
    START WITH PARENTOID=-1 
    CONNECT BY PRIOR t.id = t.parent_id 
    ) 
GROUP BY TaskName Having Sum(Hours) > 0 ORDER BY TaskName 
+0

感謝您的幫助!我已經嘗試了左外部連接選項,但它極大地減慢了查詢速度。也許我應該再看看那些表中的索引......也許在某個地方有一個缺失。但是目前RenderLn提出的解決方案就是我所期待的。再次感謝您的幫助。 – 2010-05-27 15:33:41

+0

我想到的索引(只是通過查看這個查詢)是在'timesheets'上,'task_id'的索引(假設tasks.id已經是一個索引)。但是,一般來說,外連接比內連接要慢。 – FrustratedWithFormsDesigner 2010-05-27 15:48:17