Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1259 connectés 

  FORUM HardWare.fr
  Programmation
  SQL/NoSQL

  [ORACLE] Pagination et tri (order by)

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[ORACLE] Pagination et tri (order by)

n°1563657
Alisteroid
Posté le 22-05-2007 à 17:49:41  profilanswer
 

J'ai un gros problème, je suis débutant sous oracle, et j'ai besoin de faire une liste paginée avec un tri sur chaque colonne.

 

Ca fait des heures que je cherche comment effectuer cette pagination en utilisant des clauses order by group by dans mes requetes, mais après pas mal de recherches, je ne trouve rien qui marche.

 

Dès que je tri ma liste, les elements de la nième page ne sont plus les mêmes, et je ne peux pas faire de order by rowid a cause de mes clauses group by...

 

Pour info voila la tête de ma requete :

 
Code :
  1. SELECT  GROUPE,
  2.  REPLACE(NOM_SIEGE,'*') as NOM,
  3.  SUM(NB) AS PERS_RAPPR,
  4.  SUM(VS) as VS,
  5.  SUM(VG) as VG,
  6.  //etc
  7. FROM SIEGES,
  8.  (
  9.   SELECT COUNT(*) as NB,
  10.    SUM(decode (RAPM_CODE_VIGI , 'VS', 1 , 'VG', 0, 'VC', 0, 'VV', 0, '', 0)) AS VS,
  11.    SUM(decode (RAPM_CODE_VIGI , 'VG', 1 , 'VS', 0, 'VC', 0, 'VV', 0, '', 0)) AS VG,
  12.    //etc
  13.                         LPAD(RAPM_GROUPE,5,'0') as GROUPE
  14.   from RAPPRO_PERS_MORALE ,
  15.                                LNK_RAPM_TRR 
  16.   WHERE 1=1 
  17.   AND RAPM_DR =08040
  18.   AND LNK_RAPM_TRR.RAPM_ID_PM = RAPPRO_PERS_MORALE.RAPM_ID_PM
  19.   GROUP BY RAPM_GROUPE
  20.   union all     
  21.   SELECT COUNT(*),
  22.    SUM(decode (VGPP_PART_VIGI , 'VS', 1 , 'VG', 0, 'VC', 0, 'VV', 0, '', 0)) AS VS,
  23.    SUM(decode (VGPP_PART_VIGI , 'VG', 1 , 'VS', 0, 'VC', 0, 'VV', 0, '', 0)) AS VG,
  24.    //etc
  25.    0,
  26.    0,
  27.    0,
  28.    LPAD (VGPP_GROUPE,5,'0') as GROUPE
  29.   from vigilance 
  30.   WHERE 1=1 
  31.   AND VGPP_DR =08040
  32.   GROUP BY VGPP_GROUPE,
  33.   VGPP_PART_VIGI)
  34. WHERE GROUPE = SIEGES.CODE_SIEGE 
  35. GROUP BY GROUPE,NOM_SIEGE order by nom DESC
 

J'ai essayé d'appliquer cette méthode (ou ci-dessous) mais sans succès, la pagination marche (50 par 50 ici), mais je ne peux pas me servir des critères de tri (order by n'importe quel champ du 1er select bien sur) car oracle refuse le order by rowid sur un group by :/

Code :
  1. select *
  2.   from ( select /*+ FIRST_ROWS(n) */
  3.   a.*, ROWNUM rnum
  4.       from ( ma_requete,
  5.       order by un_champ, rowid) a
  6.       where ROWNUM <= 150
  7. where rnum  >= 100;
 

Chaque fleche sur la photo ci dessous tri la liste par ordre croissant ou decroissant de nom, vs ou autre...
Si je pagine la liste, et que je n'utilise pas les critères de tri, je n'ai pas besoin de faire un order by rowid apparement d'apres le lien ou j'ai trouvé la solution de pagination
Par contre si je tri sans mettre ce 'order by rowid', par exemple je me positionne sur la page 1 (le nom des lignes  va de 'a' à 'h', si je tri par nom desc je n'aurait pas les ligne inversées (de 'h' à 'a' ) mais de 'z' à ' r', le tri ne se fera pas que sur les éléments de la page 1 mais sur toute la liste comme s'il elle n'était pas paginée et donc les élements de ma page 1 après le tri n'ont plus rien avoir avec ce qu'il était avant.

 

http://img502.imageshack.us/img502/488/hfrid6.jpg

 

Si vous pouviez me donner un coup de main ça me sauverai car je suis dans une impasse :cry:, je pense qu'il y a un moyen d'implémenter ce qui est écris dans le lien, mais je n'y parviens pas.

 

EDIT : Désolé d'avoir trafiqué le screen, données sensibles oblige :/


Message édité par Alisteroid le 22-05-2007 à 19:11:24
mood
Publicité
Posté le 22-05-2007 à 17:49:41  profilanswer
 

n°1563696
MagicBuzz
Posté le 22-05-2007 à 19:03:10  profilanswer
 

OK, je viens de piger ton problème.
 
Il faut dire que c'est assez étrange ton truc : normalement, le tri fonctionne comme tu ne veux pas. En tout cas, j'ai toujours vu faire comme ça ;)
 
Effectivement, la pagination se fait une fois les données triées, et non l'inverse.
 
Toi, ce que tu semble vouloir faire, c'est trier une seconde fois le résultat, pour afficher les données paginées selon un autre tri que le tri principal...
En soit, c'est un peu bordelique, dans la mesure ou l'utilisateur doit spécifier deux tris distincts, à moins que celui "global" ne soit "en dur".
 
Bon, je vais voir ce que je peux faire. A mon avis, c'est très simplement résolvable avec deux order by : un au niveau de ta sous-requête, et un second ensuite dans la requête finale... Mais cela demande un niveau supplémentaire d'imbrication. J'espère qu'Oracle va comprendre ton idée farfelue ;)

n°1563698
MagicBuzz
Posté le 22-05-2007 à 19:05:09  profilanswer
 

Dans mon test, je vais faire ceci :
 
Requête principale : recherche des commandes d'une base, avec comme informations : numéro de commande, nombre de lignes de la commande, et montant total de la commande
 
Premier tri permettant de trier mes pages par "numéro de commande".
Second tri permettant de trier l'intérieur de ma pase par "nombre de produits"

n°1563702
Alisteroid
Posté le 22-05-2007 à 19:12:24  profilanswer
 

Merci beaucoup MagicBuzz :jap:, je crois que je suis pas sorti du taf avant  minuit :D

n°1563703
MagicBuzz
Posté le 22-05-2007 à 19:12:41  profilanswer
 

Ben en fait, c'est tout peanuts, même pas besoin de rajouter un niveau :

Code :
  1. SELECT numeve, nblig, montant
  2. FROM
  3. (
  4.     SELECT rownum ligne, numeve, nblig, montant
  5.     FROM
  6.     (
  7.         SELECT eve.numeve, count(*) nblig, sum(evp.qtecde * evp.prxvdu) montant
  8.         FROM eve
  9.         INNER JOIN evp ON evp.codsoc = eve.codsoc AND evp.achvte = eve.achvte AND evp.numeve = eve.numeve
  10.         WHERE eve.codsoc = 2
  11.         AND eve.achvte = 'V'
  12.         AND eve.typeve = 'CDV'
  13.         AND eve.dateve LIKE '200705%'
  14.         GROUP BY eve.numeve
  15.         ORDER BY numeve
  16.     )
  17.     WHERE rownum < 150
  18. )
  19. WHERE ligne > 140
  20. ORDER BY nblig


 
Explication :

Code :
  1. SELECT eve.numeve, count(*) nblig, sum(evp.qtecde * evp.prxvdu) montant
  2. FROM eve
  3. INNER JOIN evp ON evp.codsoc = eve.codsoc AND evp.achvte = eve.achvte AND evp.numeve = eve.numeve
  4. WHERE eve.codsoc = 2
  5. AND eve.achvte = 'V'
  6. AND eve.typeve = 'CDV'
  7. AND eve.dateve LIKE '200705%'
  8. GROUP BY eve.numeve
  9. ORDER BY numeve


 
Recherche des informations sur les commandes du mois de mai triées par numéro de commandes.
 

Code :
  1. SELECT rownum ligne, numeve, nblig, montant
  2. FROM
  3. (
  4.     SELECT eve.numeve, count(*) nblig, sum(evp.qtecde * evp.prxvdu) montant
  5.     FROM eve
  6.     INNER JOIN evp ON evp.codsoc = eve.codsoc AND evp.achvte = eve.achvte AND evp.numeve = eve.numeve
  7.     WHERE eve.codsoc = 2
  8.     AND eve.achvte = 'V'
  9.     AND eve.typeve = 'CDV'
  10.     AND eve.dateve LIKE '200705%'
  11.     GROUP BY eve.numeve
  12.     ORDER BY numeve
  13. )
  14. WHERE rownum < 150


 
On ne garde que les 150 premières commandes.
 

Code :
  1. SELECT numeve, nblig, montant
  2. FROM
  3. (
  4.     SELECT rownum ligne, numeve, nblig, montant
  5.     FROM
  6.     (
  7.         SELECT eve.numeve, count(*) nblig, sum(evp.qtecde * evp.prxvdu) montant
  8.         FROM eve
  9.         INNER JOIN evp ON evp.codsoc = eve.codsoc AND evp.achvte = eve.achvte AND evp.numeve = eve.numeve
  10.         WHERE eve.codsoc = 2
  11.         AND eve.achvte = 'V'
  12.         AND eve.typeve = 'CDV'
  13.         AND eve.dateve LIKE '200705%'
  14.         GROUP BY eve.numeve
  15.         ORDER BY numeve
  16.     )
  17.     WHERE rownum < 150
  18. )
  19. WHERE ligne > 140
  20. ORDER BY nblig


 
On ne prends parmis que les 150 sélectionnées qu'à partir de 140, en triant cette fois par nblignes.
Et ça marche :p

n°1563704
MagicBuzz
Posté le 22-05-2007 à 19:13:05  profilanswer
 

D'autres questions ? :D

n°1563711
Alisteroid
Posté le 22-05-2007 à 19:38:57  profilanswer
 

T'es un dieu :D
 
C'était super con, merci encore et encore pour ta patience et ta sympathie :jap:
 
EDIT: J'ai bien testé et ça marche nickel  [:dawak]


Message édité par Alisteroid le 22-05-2007 à 19:39:35
n°1563724
Alisteroid
Posté le 22-05-2007 à 20:33:58  profilanswer
 

Ahhhhhhhhh comment je fais pour avoir le nombre de lignes qu'aurait retourné la requete sans la pagination?

n°1563769
Alisteroid
Posté le 23-05-2007 à 07:22:10  profilanswer
 

Bon je suis désolé MagicBuzz, mais je me rends compte que ce que je voulais faire est compltement débile , ça doit être la fatigue, je me retrouve à ne plus pouvoir trier ma liste entierement mais uniquement page -> sans intéret.

 

Etant donné que de limiter le nombre d'enregistrement revient au même que de tout prendre au niveau perf, autant que je fasse un array_slice() sur mon tableau avant l'affichage (enfin je crois, a moins que tu connaisses une bonne syntaxe pour gagner en perf, mais pour l'instant je vois aucune différence entre paginer 10 par 10 ou afficher 400 d'un coup) .


Message édité par Alisteroid le 23-05-2007 à 09:36:40
n°1563792
MagicBuzz
Posté le 23-05-2007 à 09:38:04  profilanswer
 

Le souci, c'est que si demain tu passes à une architecture n-Tiers (SGBD et application sur deux serveurs distincts) tu vas avoir un problème de bande passante entre les deux.
 
Effectivement, à un pouillème prêt, en local, récupérer 10 lignes dans une requête, ou 100 000 lignes, ça change pas grand chose (faut quand même penser à l'occupation mémoire qui se prends une sérieuse claque mais bon).
 
Par contre, quand les 10 ou 100 000 lignes passent à travers une connexion réseau, même en 1 Gbps, y'a une réelle différence.
 
Bon, après, passer de 10 à 400, c'est moins parlant, d'autant que si les lignes sont pas trop grosses, si ça se trouve ça va même pas générer de trame supplémentaire :D
 
Sinon, après c'est en fonction du langage d'interrogation.
Avec ADODB, on peut faire un select sans filtre (donc 100 000 lignes) qui restent sur le serveur, récupérer le nombre de lignes, puis récupérer sur le client uniquement les lignes "140 à 150". Je te laisse chercher dans la doc de ton langage (PHP ?) pour voir si tu peux reproduire un tel comportement.
 
En gros, faut que tu regardes s'il existe des "recordset serveurs".

mood
Publicité
Posté le 23-05-2007 à 09:38:04  profilanswer
 

n°1563795
Alisteroid
Posté le 23-05-2007 à 09:47:52  profilanswer
 

Mouais, je vois , ma base est assez légère (30Mo) et au pire je fais un calcul sur pratiquement (sum) tout mais le résultat de ma requete ne me retourne au pire que 500 lignes, et seulement une dixaine de champs.
 
D'après ce que tu viens de me dire, je doute qu'il soit utile de me prendre la tête.

n°1563797
Alisteroid
Posté le 23-05-2007 à 09:48:11  profilanswer
 

Merci beaucoup de ton explication en tout cas ;)


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  SQL/NoSQL

  [ORACLE] Pagination et tri (order by)

 

Sujets relatifs
[Oracle] Requete sur les schémas.Aide requete oracle, sum sur 2 tables différentes
[oracle] nom de table en argument d'une procedureAide creation requete oracle
[oracle] vue sur plusieurs tables a la structure identiqueproblème: Pagination moteur de recherche
Oracle : convertion décimalPrésentation sur Oracle 9i
Script - Base de donnéesconnexion à une base oracle avec DBI
Plus de sujets relatifs à : [ORACLE] Pagination et tri (order by)


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR