Bonsoir,
je viens vous demander votre aide car j'ai un petit problème de performance sur une de mes requêtes, j'ai la table suivante qui représente une badgeuse:

Date_heure, Ville, id_personne, sens
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
19/03/2010 08:00:53, 'Bordeaux', 1, 'IN'
19/03/2010 10:00:53, 'Bordeaux', 1, 'OUT'
 
19/03/2010 11:00:53, 'Talence', 1, 'IN'
19/03/2010 20:00:53, 'Talence', 1, 'OUT'
 
20/03/2010 08:00:53, 'Bordeaux', 1, 'IN'
20/03/2010 10:00:53, 'Bordeaux', 1, 'OUT'
 
20/03/2010 11:00:53, 'Bordeaux', 1, 'IN'
20/03/2010 20:00:53, 'Bordeaux', 1, 'OUT'
Pour identifier les premiers et derniers évènements (sans se soucier de la ville sur laquelle la personne pointe), j'ai la requête suivante:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
select to_char(date_heure,'mm-yyyy') as months,to_char(date_heure,'dd/mm/yyyy') as horo,id_personne,
min(CASE WHEN sens= 'IN' THEN to_char
(date_heure,'dd/mm/yyyy hh24:mi:ss') ELSE NULL END) as day_first_entry,
max(CASE WHEN sens= 'IN' THEN to_char
(date_heure,'dd/mm/yyyy hh24:mi:ss') ELSE NULL END) as day_last_entry,
min(CASE WHEN sens= 'OUT' THEN to_char
(date_heure,'dd/mm/yyyy hh24:mi:ss') ELSE NULL END) as day_first_exit,
max(CASE WHEN sens= 'OUT' THEN to_char
(date_heure,'dd/mm/yyyy hh24:mi:ss') ELSE NULL END) as day_last_exit
from test
group by to_char(date_heure,'mm-yyyy'), to_char(date_heure,'dd/mm/yyyy'), id_personne;
qui me retourne le résultat:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
month, date_heure, id_personne, day_first_entry,day_last_entry, day_first_exit, day_last_exit
03-2010, 19/03/2010 , 1, 19/03/2010 08:00:53, 19/03/2010 11:00:53, 19/03/2010 10:00:53, 19/03/2010 20:00:53
Ce résultat je l'utilise ensuite dans une sur-requête qui compte le nombre d'heures de présences pour chaque personne par jour.

De l'autre côté, pour des besoins statistiques, je dois rattacher chaque personne à une ville de référence en se basant sur le nombre max d'occurrences d'évenements par personne, avec la requête suivante:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
          select pers,ville
          from
          (
            select id_personne AS pers,ville,count(id_personne), rank() OVER (partition by id_personne order by count(id_personne) DESC ) as rank
            from test
          ) 
          where rank=1;
qui me renvoie le résultat suivant:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
PERS                   VILLE                          
1                      Bordeaux
Actuellement je fais donc un inner join de cette requête avec l'autre pour obtenir la ville de référence pour la personne.

Mon problème, par rapport à cette approche est qu'il faut faire 2 passage sur la table qui sont très consommateur en terme de temps sur cette même table pour obtenir 2 types d'informations différentes.

En fait, je souhaiterais diminuer au maximum le nombre de passage sur la table mais j'ai comme toujours un problème conceptuel car dans la première requête je ne me soucis pas de la ville, et dans la deuxième requête je compte les nombres d'occurrences par ville, donc 2 approches différentes.

Le résultat attendu serait
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
19/03/2010 , 1, 19/03/2010 08:00:53, 19/03/2010 11:00:53, 19/03/2010 10:00:53, 19/03/2010 20:00:53, Bordeaux
20/03/2010 , 1, 20/03/2010 08:00:53, 20/03/2010 11:00:53, 20/03/2010 10:00:53, 20/03/2010 20:00:53, Bordeaux
Pourquoi Bordeaux, car il y a 4 évènements pour cette personne et pour la ville de Bordeaux par rapport à Talence qui n'en n'a que 2.

Auriez-vous éventuellement des suggestions pour simplifier les choses ?

Merci.