2010-10-09 10 views
0

désolé pour le titre mais je ne suis pas sûr de savoir comment je devrais l'appeler. J'utilise PostgreSQL 8.3 et serait bien avec les propositions de requête non-ansi.Groupe complexe par requête (récursif?)

Supposons que ce schéma:

TimeEntries 
id    - int 
entry_date  - date 
tracked_seconds - int 
project_id  - int 

projects 
id    - int 
name   - string 
path   - string 

projets sont hirachical, je ne me soucie pas de id_parent etc. plutôt que j'ai opté pour la colonne de chemin, par exemple:

Renovate Home - path = renovate-home 
- Clean Kitchen - path = renovate-home/clean-kitchen 

Je veux une requête renvoie les éléments suivants:

date - project_path - tracked_seconds(this project) - tracked_seconds (total of self and child projects) 

groupés par date et plusieurs fois par chemin de projet pour exemple da ta:

projects 
name   path 
Funny   funny 
- Project  funny/project 
-- Is Funny funny/project/is-funny 
Foo   foo 
- Bar   foo/bar 

S'il y a maintenant TimeEntries pour drôle/projet et foo/bar et je lance cette requête:

SELECT   entry_date, p.path as project_path, sum(tracked_seconds)/60 
FROM   time_entries te 
LEFT JOIN  projects p on te.project_id = p.id 
GROUP BY  entry_date, p.path 

Je reçois ce résultat:

entry_date  project_path   ?sum? 
2010-10-01  funny/project   20 
2010-10-01  foo/bar    10 

Ce que je veux est ce:

entry_date  project_path   direct_sum  total 
2010-10-01  funny     0    20 
2010-10-01  funny/project   20    20 
2010-10-01  foo     0    10 
2010-10-01  foo/bar    10    10 

Répondre

0

Êtes-vous bloqué avec la version 8.3 ou pouvez-vous passer à la version 8.4?

Parce qu'avec 8,4, je pense que cela pourrait être résolu en utilisant des fonctions de fenêtrage:

 
SELECT te.entry_date, 
     te.tracked_seconds, 
     p.path, 
     sum(tracked_seconds) over (partition by (string_to_array(path, '/'))[1] order by entry_date asc, path desc) 
FROM TimeEntries te 
JOIN projects p ON te.project_id = p.id 
ORDER BY entry_date 
0

Cette requête ough t pour vous rapprocher de votre objectif:

SELECT   entry_date, p.path as project_path, p2.path, sum(tracked_seconds)/60 
FROM   time_entries te 
LEFT JOIN  projects p on te.project_id = p.id 
LEFT JOIN  projects p2 on p2.path LIKE p.path + '/%' 
GROUP BY  entry_date, p.path, p2.path 
+0

C'est ce que je suis également venu avec, encore je dois filtrer dans mon application et qui pourrait être fait avec project_path seul. Quoi qu'il en soit merci pour l'effort – Maxem

+0

juste une note rapide: + ne fonctionne pas pour la concaténation de caractères en SQL standard (et donc cela ne fonctionne pas dans PostgreSQL) –

+0

@a_horse_with_no_name - merci, je ne l'avais pas réalisé. Cela fonctionne à peine en T-SQL, je dois dire - plus souvent que je n'ai pas à contraindre une valeur ou une autre à une chaîne de caractères afin de ne pas essayer de convertir une chaîne par exemple. un nombre entier. –