2010-05-27 83 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