Group By & Order By Oracle

Group By & Order By Oracle - SQL/NoSQL - Programmation

Marsh Posté le 13-06-2005 à 12:03:07    

Salut a tous,
 
Je cherche a faire une petite requete simple :  
 

Code :
  1. SELECT ARTICLES.LIB_L as "Libellé Article",
  2.    FRN.LIB_L as "Libellé fournisseur",
  3.    SUM(F_STAT_VENTE_M.CA_TTC) as "CA TTC"
  4. FROM F_STAT_VENTE_M,FRN,ARTICLES
  5. WHERE F_STAT_VENTE_M.ID_MOIS=concat(substr((to_char(sysdate-30, 'YYYY')),1,4),substr((to_char(sysdate-30, 'MM')),1,2))
  6. AND F_STAT_VENTE_M.ID_ART=ARTICLES.ID_ART
  7. AND ARTICLES.ID_FRN=FRN.ID_FRN
  8. AND ROWNUM<51
  9. GROUP BY ARTICLES.LIB_L,FRN.LIB_L
  10. ORDER F_STAT_VENTE_M.CA_TTC DESC                                                          // C'est la que ca marche pas!


 
Je n'arrive pas en fait a faire trier dans l'ordre descendant les SOMME des CA.  
Quelqu'un a t-il une idée?
 
Merci
 
M.

Reply

Marsh Posté le 13-06-2005 à 12:03:07   

Reply

Marsh Posté le 13-06-2005 à 12:07:31    

Citation :


ORDER BY SUM(F_STAT_VENTE_M.CA_TTC) DESC  


Message édité par denzz le 13-06-2005 à 12:08:46
Reply

Marsh Posté le 13-06-2005 à 12:11:17    

merci... ca marche!
Pourtant j'etais persuadé d'avoir essaye!
 
Je dois etre bete... :(

Reply

Marsh Posté le 13-06-2005 à 12:17:47    

ca arrive à tout le monde :) et c toujours dur de relire de manière critique un code qu'on écrit soi-même :jap:

Reply

Marsh Posté le 13-06-2005 à 12:19:28    

hehe, c'est vrai!
 
Par contre, ma fonction "rownum" ne me renvoie pas ce que je voudrais.
 
En fait, il faudrait que cette requete me retourne les 50 premieres lignes de celle-ci.
 
En fait, un peu comme la fonction 'limit' en MySQL...
Tu as une idée?

Reply

Marsh Posté le 13-06-2005 à 13:35:53    

oui, regarde dans la documentation sql de ton server oracle, il doit y avoir moyen de faire l'équivalent non ?  
sinon, en fonction de ce que tu utilises comme langage de prog derrière, tu dois avoir dans les fonctions de ton connecteur oracle qqch qui te permet de le faire au niveau prog....

Reply

Marsh Posté le 13-06-2005 à 14:18:03    

Voilà comment j'ai contourné, je sais pas si c'est propre, mais ca marche bien:
 

Code :
  1. SELECT *
  2. FROM
  3. (SELECT ARTICLES.LIB_L as "Libellé Article",
  4.    FRN.LIB_L as "Libellé fournisseur",
  5.    SUM(F_STAT_VENTE_M.CA_TTC) as "CA TTC"
  6. FROM F_STAT_VENTE_M,FRN,ARTICLES
  7. WHERE F_STAT_VENTE_M.ID_MOIS=concat(substr((to_char(sysdate-30, 'YYYY')),1,4),substr((to_char(sysdate-30, 'MM')),1,2))
  8. AND F_STAT_VENTE_M.ID_ART=ARTICLES.ID_ART
  9. AND ARTICLES.ID_FRN=FRN.ID_FRN
  10. GROUP BY ARTICLES.LIB_L,FRN.LIB_L
  11. ORDER BY SUM(F_STAT_VENTE_M.CA_TTC) DESC)
  12. WHERE ROWNUM<51

Reply

Marsh Posté le 13-06-2005 à 14:23:37    

effectivement, ce n'est pas très très propre, mais on s'en fout je suis pas là pour donner des cours de requêtes propres :)
si ca fait bien ce que tu veux, et que tu n'a pas besoin de prendre ensuite les 50 résultats suivants, etc .. ca devrait suffire :)

Reply

Marsh Posté le 13-06-2005 à 17:02:32    

jay-jay69 a écrit :

merci... ca marche!
Pourtant j'etais persuadé d'avoir essaye!
 
Je dois etre bete... :(


essaie plutôt [order by "CA TTC"], c'est moins long à écrire. ceci dit, normalement ça change rien au fonctionnement de la requête, Oracle n'est pas censé calculer les valeurs du Order By. Sous SQL Server, par contre, c'est moins sur, étant donné que ce genre de requêtes marche, alors que sous Oracle je ne crois pas :
 

Code :
  1. select a, b
  2. from latable
  3. order by a * c


 
=> Avec "c" membre de la table, et non retourné par la requête, sans parler du calcul, qui ne figure pas dans la clause select non plus.

Reply

Marsh Posté le 13-06-2005 à 17:06:04    

Sinon, pour le ROWNUM, y'a en effet pas d'autre solution.
 
Pour information, le ROWNUM numérote les lignes non pas dans l'ordre du résultat de la requête, mais dans la table (ou table temporaire, quand il y a un sous-select).
 
En effet, tu peux tenter ça :
 
Une table avec les données :
 

Code :
  1. a   b
  2. ------
  3. 1   5
  4. 2   6
  5. 8   4
  6. 9   10
  7. 5   20


 
Si tu fais :
 

Code :
  1. select a, b from matable
  2. where rownum <= 3
  3. and b > 4


 
Alors tu auras ça :

Code :
  1. a   b
  2. ------
  3. 1   5
  4. 2   6


 
Et non pas :
 

Code :
  1. a   b
  2. ------
  3. 1   5
  4. 2   6
  5. 9   10


Message édité par Arjuna le 13-06-2005 à 17:06:20
Reply

Marsh Posté le 13-06-2005 à 17:06:04   

Reply

Marsh Posté le 13-06-2005 à 19:58:34    

Pour le "order by" c'est plus simple de faire "by 1 desc",  1 étant le premier champ sélectionné et ainsi de suite ... Tout bête mais si facile ...

Reply

Marsh Posté le 13-06-2005 à 20:09:02    

Merci les gars, c'est gentil! J'apprends des trucs au passage, ca fait plaisir! Et c'est bien expliké!

Reply

Marsh Posté le 13-06-2005 à 22:14:36    

mosca > ouais, mais ça marche pas partout (sous SQL Server ça marche pas)
 
deplus, comme le "select *", je le déconseille très vivement (et heureusement, beaucoup de boîtes informatiques luttent dans le même sens), ça si pour le débug, ou la phase de développement d'une requête, c'est intéressant, le jour ou on passe en prod, il ne faut jamais conserver ses types "d'optimisation de l'écriture", pour la simple et bonne raison que lorsqu'on a une requête très longue, ou générer en plusieurs fois par un algorithme complexe, on risque d'introduire des erreurs graves en maintenance alors qu'on fait une simple modification "sans danger".
 
Exemple :
 
J'ai la requête :

Code :
  1. select nom, age
  2. from personne
  3. order by 1


 
Et là, mince, je m'apperçois que j'ai oublié d'afficher le prénom. Comme j'afficherai "prénom nom", je modifie comme un con la requête en ajoutant simplement "prenom" devant "nom". C'est censé n'avoir aucun impact sur le programme. Et pourtant, je viens de planter l'ordre d'affichage ! Si "nom" est spécifié dans le "order by", alors je n'aurai pas ce problème.
 
Un autre élément classique, avec le "*" cette fois. J'ai une table "commande". Afin de conserver une historisation des modifications dans mes commandes, j'ai un trigger qui alimente une table "commandeshisto" afin de conserver une trace des lignes modifiées.
Le trigger alimentera donc la table comme suit :
 

Code :
  1. insert into commandeshisto (select *, userid, sysdate from deleted)


 
Que se passe-t-il si j'ajoute un champ acceptant les null dans ma table "commandes" ? A priori, c'est une modification sans danger. Cependant, le trigger va se retrouver avec un champ de trop lors de l'insert, et vlan ! On ne pourra plus faire la moindre modification dans la table sans produire une erreur. PIRE, dans certains cas, parceque l'appli a été mal développée, on va enregistrer les modifications dans la table, sans en conserver l'historique, et en cas de problème, plusieurs mois après, on va se retrouver face à une table des historiques vide.
 
Donc, le "order by 1" et le "select *", c'est bien sympa quand on est en train d'écrire la requête, mais c'est à banir du code final, même si c'est un eu plus chiant a écrire :)

Reply

Marsh Posté le 13-06-2005 à 22:20:51    

PS: pour le second cas, je l'ai vécu pas plus tard que ces derniers mois.
J'ai du rendre "multi-société" une base de données, c'est à dire ajouter dans la plupart des tables un champ "orgid" membre de la clé primaire, correspondant à l'organisation rattachée à chaque ligne.
 
J'ai pris mes mimines, et recherché dans deux documents de 100 000 lignes (scripts de génération SQL de deux bases impactées par cette modification). Evidement, 200 000 lignes à regarder une à une, au bout d'un moment, on ne fait plus trop gaffe à ce qu'on fait. Et du coup, j'ai fini par de simple "search" avec mon éditeur de texte, afin de retrouver les appels aux champs des tables modifiées dans les procédures stockées. Et là, y'a tout bonnement 12 triggers qui sont passés tout debout à cause de ces *.
Je remercie Microsoft du fond du coeur de faire une vérification automatique de l'intégrité des requêtes des objets liés lors d'une modification dans une table, parceque sinon, lorsque j'ai appliqué mes modifications, je n'aurais jamais trouvé ces triggers. J'ai donc pu les modifier à temps avant de produire une catastrophe.


Message édité par Arjuna le 13-06-2005 à 22:21:53
Reply

Marsh Posté le 13-06-2005 à 22:57:27    

Arjuna a écrit :

mosca > ouais, mais ça marche pas partout (sous SQL Server ça marche pas)
 
deplus, ...


 
Ok, mais il a bien dit dans son titre "sous oracle" ...
Sinon, le "order by 1" ou "by nom", c'est une question de rigueur à l'écriture du query ... Tout le monde teste l'affichage de son query pour voir si ça correspond au résultat attendu ...

Reply

Marsh Posté le 14-06-2005 à 11:53:55    

ouais, mais 99% des gens font ensuite un simple copier/coller dans leur application sans se poser de question une fois que leur requête en cours de développement fonctionne. à partir de là, moi je vote et je dis "c'est mal" :p

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed