Domanda

Ho bisogno di aiuto con una query di Oracle.

Qui è la mia messa a punto:

Ho 2 tabelle denominate rispettivamente "compiti" e "schede". La tabella "compiti" è un ricorsiva, in questo modo ogni attività può avere più attività secondarie. Ogni scheda attività è associata un'attività (non necessariamente il task "root") e contiene il numero di ore di lavoro su di esso.

Esempio:

Attività

id: 1 | NOME: Task A | parent_id: NULL

id: 2 | Nome: Task A1 | parent_id: 1

id: 3 | Nome: Task A1.1 | parent_id: 2

id: 4 | Nome: Task B | parent_id: NULL

id: 5 | Nome: Task B1 | parent_id: 4

Schede attività

id: 1 | task_id: 1 | ore: 1

id: 2 | task_id: 2 | ore: 3

id: 3 | task_id: 3 | ore: 1

id: 5 | task_id: 5 | ore: 1 ...

Cosa voglio fare:

Voglio una query che restituirà la somma di tutte le ore di lavoro su una "gerarchia delle attività". Se diamo uno sguardo l'esempio precedente, Vuol dire vorrei avere i seguenti risultati:

compito A - 5 hour (s) | compito B - 1 ora (s)

In un primo momento ho provato questo

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

E quasi lavoro. L'unico problema è che se non ci sono scheda attività per un'attività root, salterà tutta hieararchy ... ma ci potrebbe essere schede per le righe figlio ed è esattamente ciò che accade con Task B1. So che è il "join interna" parte che sta causando il mio problema, ma io non sono sicuro di come posso liberarmi di esso.

Qualsiasi idea di come risolvere questo problema?

Grazie

È stato utile?

Soluzione

Sarebbe qualcosa di simile a questo lavoro? Ho avuto casi simili ai tuoi, e ho semplicemente rimosso il join dalla query gerarchica e applicai soltanto in seguito per evitare di perdere le righe.

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

Altri suggerimenti

Hai provato questo?

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

Se si utilizza join esterno sinistro al posto del normale join, è possibile ottenere l'output.

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 
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top