【问题标题】:Mixing together Connect by, inner join and sum with Oracle与Oracle混合Connect by、inner join和sum
【发布时间】:2010-05-27 14:49:04
【问题描述】:

我需要有关 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 |任务ID:1 |小时:1

id:2 |任务ID:2 |小时:3

id:3 |任务ID:3 |小时:1

id:5 |任务ID:5 |小时:1 ...

我想做什么:

我想要一个查询,该查询将返回在“任务层次结构”上工作的所有小时数的总和。如果我们看一下前面的例子,这意味着我想得到以下结果:

任务 A - 5 小时 |任务 B - 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 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 发生的情况。我知道是“内部连接”部分导致了我的问题,但我不确定如何才能摆脱它。

知道如何解决这个问题吗?

谢谢

【问题讨论】:

  • 我认为如果你颠倒表格的顺序并使用左外连接,即使没有时间表,你也会得到任务,以便可能工作......也许?
  • 感谢您的帮助。在我的情况下进行左连接会导致一些主要的性能问题......即使这些表都被很好地索引了。

标签: oracle connect-by


【解决方案1】:

这样的东西会起作用吗?我遇到过与您类似的情况,我只是从分层查询中删除了联接,然后才应用它以避免丢失行。

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

【讨论】:

  • 感谢一百万!我认为这是在起作用。还要进行一些测试,我会将其标记为官方答案。
【解决方案2】:

你试过了吗?

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

【讨论】:

  • 感谢您的帮助!我已经尝试了左外连接选项,但它极大地减慢了查询速度。也许我应该再看看那些表中的索引......也许某处缺少一个。但目前 RenderLn 提出的解决方案正是我正在寻找的。再次感谢您的帮助。
  • 我会想到的索引(仅通过查看此查询)位于timesheetstask_id 的索引(假设 tasks.id 已经是一个索引)。但是,是的,一般来说,外连接比内连接慢。
【解决方案3】:

如果你使用左外连接而不是普通连接,你可能会得到输出。

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 

【讨论】:

  • 我认为他也必须颠倒表格的顺序,因为他想要没有相应时间表的任务。目前,如果他改为左外,他会得到没有相应任务的时间表。
  • FrustratedWithFormsDesigner:你是对的,或者他也可以使用右外连接
猜你喜欢
  • 2013-09-05
  • 2016-04-10
  • 1970-01-01
  • 1970-01-01
  • 2016-05-22
  • 2017-12-07
  • 1970-01-01
  • 2015-08-21
  • 1970-01-01
相关资源
最近更新 更多