Смешивание вместе соединения, внутреннее соединение и сумма с Oracle

StackOverflow https://stackoverflow.com/questions/2922167

  •  05-10-2019
  •  | 
  •  

Вопрос

Мне нужна помощь с запросом Oracle.

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

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

Пример:

Задачи

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 час (ы)

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

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

Любая идея, как решить эту проблему?

Спасибо

Это было полезно?

Решение

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

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

Другие советы

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

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

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

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 
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top