|
Publicité ' | ||||||||||||||||||||||||
|
|
#1 |
|
Membre confirmé
![]() Vincent Développeur informatique Inscription : janvier 2009 Messages : 248 ![]() |
Bonjour,
Je cherche depuis un bon moment comment faire une requête. Voici l'énoncé de mon problème : J'ai 3 tables qui se présentent comme suit : table des négociateur (t_negociateur) : negociateur_id | neg_nom 1 | Dupont 2 | Durant 3 | Tartanpion ... ... table des erreurs sur les offres (check_offres) : offre_id | neg_id 1 | 1 2 | 2 3 |3 4 |1 5 | 1 ... ... table des erreurs sur les demandes (check_demandes) : demande_id | neg_id 1 | 1 2 | 2 3 | 3 4 | 3 5 | 2 ... ... Et je voudrai resortir un resultat comme suit : nom du négociateur | nombre erreurs offres | nombre erreurs demandes Dupont | 64 | 26 Durant | 31 | 23 Tartanpion |28 | 37 Attention : Je voudrais sortir ce résultat en 1 seule requête pour pouvoir faciliter les tris de mon tableau par la suite. Merci d'avance de votre aide. |
|
|
00
|
|
|
#2 |
|
Membre émérite
![]() Tony Développeur .NET Inscription : novembre 2010 Messages : 570 ![]() |
Bonjour,
tu joins les 3 tables et tu fais un count(offre) et un count(demande) en groupant par negociateur |
|
|
01
|
|
|
#3 |
|
Membre confirmé
![]() Vincent Développeur informatique Inscription : janvier 2009 Messages : 248 ![]() |
Oui c'est ce que j'ai essayé mais le résultat il ne distingue pas le nombre d'erreurs offres du nombre d'erreurs demande.
|
|
|
00
|
|
|
#4 | ||||
|
Expert Confirmé
![]() Inscription : mai 2002 Messages : 1 641 ![]() |
bonjour,
je vois en gros deux solutions : Code :
et sinon Code :
A tester les deux solutions pour prendre celle qui a le meilleur plan d'acces. |
||||
|
|
10
|
|
|
#5 | ||
![]() ![]() |
Je n'aime aucune des deux solutions du dessus !
Code :
__________________
Email : http://scr.im/waldar |
||
|
10
|
|
|
#6 |
|
Membre confirmé
![]() Vincent Développeur informatique Inscription : janvier 2009 Messages : 248 ![]() |
J'ai essayé la 2eme solution mais j'obtiens le message suivant :
Msg*102, Niveau*15, État*1, Ligne*2 Syntaxe incorrecte vers ')'. avant cela j'ai déjà enlevé la virgule après la parenthèse fermante du 2eme SUM parce que j'avais une erreur dessus. Autre précision que j'ai oublié dans l'énoncé : Je dois aussi vérifier les champs : 'agence_id' et 'neg_actif' de la table t_negociateurs en faisant qqc comme : "WHERE N.agence_id=1 and N.neg_actif = 1" ... je ne pense pas que cela ait une quelconque importance mais je préfère le préciser. |
|
|
00
|
|
|
#7 | ||
|
Expert Confirmé
![]() Inscription : mai 2002 Messages : 1 641 ![]() |
ah oui j'ai oublié le end désolé,
Code :
Sinon, vous pouvez rajouter votre clause where sans aucun problème dans les 3 cas cités. |
||
|
|
10
|
|
|
#8 | ||||
|
Membre éclairé
![]() |
voilà la requete qe tu cherche
Code :
Code :
|
||||
|
|
01
|
|
|
#9 | |||
|
Membre confirmé
![]() Vincent Développeur informatique Inscription : janvier 2009 Messages : 248 ![]() |
Citation:
neg_nom | nb_off | nb_dmd Tartampion | 6 | 22 Tartampion | 0 | 0 Tartampion | 3 | 0 Je pense que c'est dut au fait que l'id de Tartampion apparait plusieurs fois dans la table t_negociateur. Que dois-je faire pour n'avoir qu'une ligne de résultat par négociateur ? |
|||
|
|
00
|
|
|
#10 |
|
Membre Expert
![]() Sylvain DevidalChef de projets Générix Inscription : février 2010 Messages : 1 062 ![]() |
Personnellement, je préfère la requête avec les sous-select dans la liste des colonnes du select, plutôt que ta solution (moins lisible je trouve).
De plus, niveau perf, je ne suis pas certain qu'il n'y trouve la moindre différence, puisque les deux font absolument la même chose (au bug près) |
|
|
00
|
|
|
#11 | ||
|
Membre Expert
![]() Inscription : août 2008 Messages : 1 271 ![]() |
Citation:
Citation:
Personnelement je me serais naturellement orienté vers les sum(case...), comme quoi les goûts et les couleurs ... Il faut donc soit choisir la requête la plus performante, soit, si les perfs sont les mêmes, celle que l'on préfère. |
||
|
|
00
|
|
|
#12 | |
|
Membre Expert
![]() Sylvain DevidalChef de projets Générix Inscription : février 2010 Messages : 1 062 ![]() |
Citation:
Dans les deux cas, l'optimiseur va de toute façon convertir les sous-select en jointures simples (ou alors on est sur MySQL ou PostGreSQL et leur optimiseur pourrave). Il est même possible que les sous-select en colonne auront un plan plus légèrement plus simple que la requête de waldar qui fait des outer join sur des sous-select. En tout cas, je doute fortement que le plan soit significativement différent. |
|
|
|
00
|
|
|
#13 |
![]() ![]() |
Non mais il n'y a pas besoin de plan d'exécution ici, il suffit de lire les requêtes.
La première requête est une requête scalaire. Elles sera efficace sur un petit nombre d'id, mais pas sur des gros volumes. Pourquoi ? Parce qu'en gros, elle va compter le nombre d'occurrence id par id dans les tables filles. La deuxième requête crée un produit cartésien entre les tables offres et demandes, et après on compte les valeurs renseignées dans ce résultats. À exclure d'office. La requête que j'ai proposée consolide d'abord les données avant de faire les jointures. Ce sera efficace quel que soit les volumétries en jeu.
__________________
Email : http://scr.im/waldar |
|
00
|
|
|
#14 | |
|
Membre Expert
![]() Sylvain DevidalChef de projets Générix Inscription : février 2010 Messages : 1 062 ![]() |
Citation:
Avec PostGreSQL ou MySQL, je dis pas, mais Oracle, absolument sûr et certain, il réécrit la requête sous forme d'une jointure simple avant de faire le comptage des lignes. Avec MS SQL Server, je n'en mettrai pas ma main à couper, mais je doute fortement qu'il ne fasse pas la même chose. Certes, je suis d'accord sur le fait que la requête laisse penser ça, mais comme vous me l'avez si bien dit, les SGBD traitent les données de façon ensembliste : dont même si on écrit une requête d'une façon scalaire, il va tenter de la traiter de façon ensembliste. Pour moi, à un détail près, la requête réellement exécutée sera celle que tu préconise. Mais d'un point de vue lecture, je trouve l'autre sémantiquement plus lisible. |
|
|
|
00
|
|
|
#15 | ||||||||
![]() ![]() |
Sur Oracle 11gR1 :
Code :
Code :
Code :
Code :
__________________
Email : http://scr.im/waldar |
||||||||
|
00
|
|
|
#16 |
|
Membre confirmé
![]() Vincent Développeur informatique Inscription : janvier 2009 Messages : 248 ![]() |
@Waldar : Grand merci pour ta solution, après avoir testé et retesté ça marche impec
![]() Et grand merci de votre aide à tous. ps : ne vous battez pas ! |
|
|
00
|
|
|
#17 | |||||||||
|
Membre Expert
![]() Sylvain DevidalChef de projets Générix Inscription : février 2010 Messages : 1 062 ![]() |
Citation:
Je viens de faire le test aussi sur une base Release 10.1.0.5.0, et j'obtiens les mêmes résultats que toi. Pourtant, j'ai déjà débattu du sujet avec un DBA sur ce sujet (sur la 8i, 9i ?) il y a quelques temps, et je suis absolument certain que le sous-select en colonne étaient convertis en jointure simple dans le plan d'exécution En tout cas, je viens de faire le test sur une base de données volumineuse : Code :
Code :
Avec ta requête : Code :
Code :
Le résultat est assez étonnant pour ta requête : récupérer 50 lignes est plus long que pour faire des calculs sur les 436000 lignes. En revanche, sur un grand volume, ta requête est effectivement plus rapide sur un traitement synchrone. Mais en traitement assynchronme, ma requête retourne des lignes immédiatement, ce qui peut être appréciable, ça dépend de ce qu'on veut en faire. Si je refais tourner les requête pour ne rammener qu'une ligne (numeve = 1000000) alors ma requête est un peu plus rapide (pour autant que de passer de 0,036 secondes à 0,012 puisse être significatif). En tout cas, je retiens, en effet, les sous-select en colonne ne sont pas (plus ?) traduits en jointures. |
|||||||||
|
|
00
|
|
|
#18 | ||
|
Membre émérite
![]() Tony Développeur .NET Inscription : novembre 2010 Messages : 570 ![]() |
Et un simple :
Code :
|
||
|
|
00
|
|
|
#19 | ||
|
Membre Expert
![]() Sylvain DevidalChef de projets Générix Inscription : février 2010 Messages : 1 062 ![]() |
Ca ne marche pas, ça fait faire un produit cartésien entre les lignes de check_offre et chech_demande, du coup les counts sont faussés.
Il faudrait trouver un ID unique par neg_id dans chacune de ces deux tables (avec la PK par exemple) et faire des count distinct dessus, en serrant très fort les fesses. En fait, il faudrait tenter ça : Code :
|
||
|
|
00
|
|
|
#20 |
|
Membre émérite
![]() Tony Développeur .NET Inscription : novembre 2010 Messages : 570 ![]() |
Etrange, j'ai pas spécialement de quoi tester la mais il me semblait que le fait de faire la jointure sur le negociateur_ID avec les NEG_ID et de grouper ensuite par négociateur_ID, le fait de faire les count après suffirait
Je ne vois pas vraiment l'interet du distinct |
|
|
00
|
Copyright © 2000-2012 - www.developpez.com