Est-ce que quelque chose comme ça fonctionnerait? J'ai eu des cas similaires au vôtre, et j'ai simplement supprimé la jointure de la requête hiérarchique et ne l'ai appliquée qu'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