Смешивание Соединитесь, внутреннее соединение и сумма с Oracle - PullRequest
4 голосов
/ 27 мая 2010

Мне нужна помощь с оракулом.

Вот мои настройки:

У меня есть 2 таблицы, которые называются соответственно «задачи» и «расписания». Таблица «Задачи» является рекурсивной, поэтому каждая задача может иметь несколько подзадач. Каждый график связан с задачей (не обязательно «корневой») и содержит количество отработанных часов.

Пример:

Задачи

id: 1 | название: Задание А | parent_id: NULL

id: 2 | название: Задание А1 | 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 час

Сначала я попробовал это

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. Я знаю, что это проблема «внутреннего соединения», которая вызывает мою проблему, но я не уверен, как мне от нее избавиться.

Есть идеи, как решить эту проблему?

Спасибо

Ответы [ 3 ]

4 голосов
/ 27 мая 2010

Хотелось бы что-нибудь подобное? У меня были случаи, похожие на ваши, и я просто удалил объединение из иерархического запроса и применил его только потом, чтобы избежать потери строк.

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
1 голос
/ 27 мая 2010

Вы пробовали это?

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 голосов
/ 27 мая 2010

Если вы используете левое внешнее соединение вместо обычного, вы можете получить вывод.

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 
...