Mélangeant Connect par, jointure interne et somme avec Oracle
-
05-10-2019 - |
Question
J'ai besoin d'aide avec une requête oracle.
Voici ma configuration:
J'ai 2 tables appelées respectivement « tâches » et « feuilles de temps ». Le tableau « tâches » est une récursive, de cette façon chaque tâche peut avoir plusieurs sous-tâches. Chaque feuille de temps est associée à une tâche (pas nécessairement la tâche « racine ») et contient le nombre d'heures travaillées sur elle.
Exemple:
Tâches
id: 1 | Nom: Groupe A | id_parent: NULL
id: 2 | Nom: Groupe A1 | parent_id: 1
id: 3 | Nom: Tâche A1.1 | parent_id: 2
id: 4 | Nom: Groupe B | id_parent: NULL
id: 5 | Nom: Tâche B1 | parent_id: 4
Timesheets
id: 1 | task_id: 1 | heures: 1
id: 2 | task_id: 2 | heures: 3
id: 3 | task_id: 3 | heures: 1
id: 5 | task_id: 5 | heures: 1 ...
Ce que je veux faire:
Je veux une requête qui renverra la somme de toutes les heures travaillées sur une « hiérarchie des tâches ». Si nous jetons un coup d'œil à l'exemple précédent, cela signifie que je voudrais avoir les résultats suivants:
A la tâche - 5 heure (s) | tâche B - 1 heure (s)
Au début, j'ai essayé cette
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
Et presque le travail. Le seul problème est que s'il n'y a pas pour une tâche timesheet racine, il ignorera toute hieararchy ... mais il pourrait y avoir des feuilles de temps pour les lignes enfants et il est exactement ce qui se passe avec la tâche B1. Je sais que c'est la partie « jointure » qui est à l'origine de mon problème, mais je ne sais pas comment puis-je en débarrasser.
Toute idée de comment résoudre ce problème?
Merci
La solution
Would quelque chose comme ce travail? J'ai eu des cas semblables à la vôtre, et je simplement supprimé la jointure de la requête hiérarchique et appliqué seulement après pour éviter de perdre des lignes.
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
Autres conseils
Avez-vous essayé?
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 vous utilisez jointure externe gauche au lieu de la normale rejoindre, vous pouvez obtenir la sortie.
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