Mezclando Connect, combinación interna y la suma con Oracle
-
05-10-2019 - |
Pregunta
Necesito ayuda con una consulta de Oracle.
Aquí está mi configuración:
Tengo 2 tablas llamadas respectivamente "tareas" y "tabla de tiempos". La tabla de "tareas" es un ser recursivo, de esa manera cada tarea puede tener varias subtareas. Cada parte de horas está asociado a una tarea (no necesariamente la tarea "raíz") y contiene el número de horas trabajadas en él.
Ejemplo:
Tareas
id: 1 | Nombre: Tarea A | parent_id: NULL
id: 2 | Nombre: Tarea A1 | parent_id: 1
id: 3 | Nombre: Tarea A1.1 | parent_id: 2
id: 4 | Nombre: Tarea B | parent_id: NULL
id: 5 | Nombre: Tarea B1 | parent_id: 4
partes de horas
id: 1 | task_id: 1 | hora: 1
id: 2 | task_id: 2 | hora: 3
id: 3 | task_id: 3 | hora: 1
id: 5 | task_id: 5 | hora: 1 ...
Lo que quiero hacer:
Quiero una consulta que devolverá la suma de todas las horas trabajadas en una "jerarquía de tareas". Si echamos un vistazo al ejemplo anterior, Significa me gustaría tener los siguientes resultados:
Una tarea - 5 hora (s) | tarea B - 1 hora (s)
Al principio traté de este
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
Y casi trabajo. El único problema es que si no hay hoja de tiempo para una tarea raíz, se omitirá toda la hieararchy ... pero podría haber tabla de tiempos para las filas secundarias y es exactamente lo que sucede con el Grupo B1. Sé que es la "combinación interna" parte que está causando mi problema pero no estoy seguro de cómo me deshago de ella.
Cualquier idea de cómo resolver este problema?
Gracias
Solución
¿Podría algo así como este trabajo? He tenido casos similares al suyo, y simplemente me quité la unión de la consulta jerárquica y se aplica sólo después para evitar la pérdida de filas.
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
Otros consejos
¿Has probado esto?
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
Si utiliza externa izquierda en lugar de unirse a la normalidad, es posible obtener la salida.
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