Requete optimisee ?

Requete optimisee ? - SQL/NoSQL - Programmation

Marsh Posté le 02-03-2005 à 15:11:33    

Pensez vous que ce genre de requete est optimisee ? g des doutes sur l optimisation de conditions de type WHERE...IN
 
SELECT GR, Nom+' '+Prenom+' ('+Matricule_Agent+')' AS Identite, Adresse, Telephone, Bureau, Mobile
FROM Agents
WHERE GR='12' AND
Matricule_Agent IN  
(SELECT DISTINCT Matricule_Agent FROM Affectations WHERE Type_Affectation=0 AND Jour>38412 AND Jour<38419)
 
les valeurs renseignees sont pour des tests
 
Merci a ceux qui donneront leur avis
 
PS: pour info c sur une base Access mais ma question est plutot generaliste donc j accepte tout avis meme si c pour du oracle, mysql, sql server, dbase & co :)

Reply

Marsh Posté le 02-03-2005 à 15:11:33   

Reply

Marsh Posté le 02-03-2005 à 15:19:03    

Une jointure passerait peut-être mieux.
 
Par contre, tu n'as pas de moyen pour éviter le distinct ?

Reply

Marsh Posté le 02-03-2005 à 15:20:38    

a priori non , g essaye par des group by (+ jointures dans la requete) mais c etait pas mieux....
En plus je viens de me rendre compte que cette requete etait trop simple pour qu elle soit pertinente au resultat que je recherche je vais devoir encore la completer :p :(

Reply

Marsh Posté le 02-03-2005 à 15:22:57    

Code :
  1. SELECT ag.matricule_agent,GR, Nom+' '+Prenom+' ('+Matricule_Agent+')' AS Identite, Adresse, Telephone, Bureau, Mobile
  2. FROM Agents ag,Affectations af
  3. WHERE (ag.matricule_agent =af.matricule_agent)
  4. AND GR='12' AND af.Type_Affectation=0 AND Jour BETWEEN 38412 AND 38419
  5. group by ag.matricule_agent


 
je vois pas l'interet d'utiliser une requete imbriquée(la structure de tes tables pourraient etre utile


Message édité par Profil supprimé le 02-03-2005 à 15:24:34
Reply

Marsh Posté le 02-03-2005 à 15:42:52    

Code :
  1. SELECT AG.GR, AG.Nom+' '+AG.Prenom+' ('+AG.Matricule_Agent+')' AS Identite,
  2. AG.Adresse, AG.Telephone, AG.Bureau, AG.Mobile, AG.Niveau_hierarchique, AG.Equipe, AG.Astreinte, CA.Intitule
  3. FROM Agents AG
  4. LEFT JOIN CodesAstreintes CA ON CA.Code_Astreinte=AG.Astreinte
  5. WHERE GR='12' AND Matricule_Agent IN
  6. (SELECT DISTINCT Matricule_Agent
  7. FROM Affectations
  8. WHERE Type_Affectation=0 AND Jour>38412 AND Jour<38419)
  9. ORDER BY CA.Intitule, AG.Niveau_hierarchique, AG.Equipe


 
Voila finalement ma requete finale...
 
heu pour la structure de mes tables, trop complique de les sortir mais je suis bien oblige d avoir 2 tables

Reply

Marsh Posté le 02-03-2005 à 16:24:16    

par contre, il me semble que les sous requetes WHERE IN sont limites en nombre d elements, qqun pourrait il me confirmer cette info et me dire combien de valeur peut on esperer recuperer ? ( 255 , + ? )  
 
Merci

Reply

Marsh Posté le 07-03-2005 à 10:52:32    

Dans un premier temps, le "DISTINCT" de la sous-requête est inutile. On le vire, allez, 10% plus rapide :)
Ensuite < and >, c'est "between". Ca change rien niveau rapidité, mais c'est plus joli.
De même, on alias les tables, et on préfixe les champs, c'est pas très utile pour le moteur de requête, mais ça aide les gens qui lisent la requête, et surtout, ça te permet de modifier la requête sans devoir passer 1 heure à remettre tout en forme.
 

Code :
  1. SELECT
  2.     a.GR,
  3.     a.Nom + ' ' + a.Prenom + ' (' + a.Matricule_Agent + ')' Identite,
  4.     a.Adresse,
  5.     a.Telephone,
  6.     a.Bureau,
  7.     a.Mobile
  8. FROM Agents a
  9. WHERE a.GR = '12' -- C'est quoi ces ' autour d'un nombre ?
  10. AND a.Matricule_Agent IN (
  11.    SELECT aff.Matricule_Agent
  12.    FROM Affectations aff
  13.    WHERE aff.Type_Affectation = 0
  14.    AND aff.Jour between 38412 38419 -- Je crois que le between est inclusif, à ce moment, c'est 38413 et 48418
  15. )


 
Maintenant, remplaçons cet affreux "IN" par un "EXISTS" (20 à 30% plus rapide, et sans limite d'élément dans la sous-requête)
 

Code :
  1. SELECT
  2.     a.GR,
  3.     a.Nom + ' ' + a.Prenom + ' (' + a.Matricule_Agent + ')' Identite,
  4.     a.Adresse,
  5.     a.Telephone,
  6.     a.Bureau,
  7.     a.Mobile
  8. FROM Agents a
  9. WHERE a.GR = '12' -- C'est quoi ces ' autour d'un nombre ?
  10. AND EXISTS (
  11.    SELECT NULL
  12.    FROM Affectations aff
  13.    WHERE aff.Matricule_Agent = a.Matricule_Agent
  14.    AND aff.Type_Affectation = 0
  15.    AND aff.Jour between 38412 38419 -- Je crois que le between est inclusif, à ce moment, c'est 38413 et 48418
  16. )


 
Et là, j'ai bien l'impression que tu pourrais simplement faire une jointure...
 

Code :
  1. SELECT
  2.     a.GR,
  3.     a.Nom + ' ' + a.Prenom + ' (' + a.Matricule_Agent + ')' Identite,
  4.     a.Adresse,
  5.     a.Telephone,
  6.     a.Bureau,
  7.     a.Mobile
  8. FROM Affectations aff, Agents a
  9. WHERE a.GR = '12' -- C'est quoi ces ' autour d'un nombre ?
  10. AND aff.Matricule_Agent = a.Matricule_Agent
  11. AND aff.Type_Affectation = 0
  12. AND aff.Jour between 38412 38419 -- Je crois que le between est inclusif, à ce moment, c'est 38413 et 48418


 
Si Matricule_Agent est doublonné dans Affectations, alors il faut faire un distinct (c'est très balo, parceque là ça pète toutes les optimisations...)
 

Code :
  1. SELECT DISTINCT
  2.     a.GR,
  3.     a.Nom + ' ' + a.Prenom + ' (' + a.Matricule_Agent + ')' Identite,
  4.     a.Adresse,
  5.     a.Telephone,
  6.     a.Bureau,
  7.     a.Mobile
  8. FROM Affectations aff, Agents a
  9. WHERE a.GR = '12' -- C'est quoi ces ' autour d'un nombre ?
  10. AND aff.Matricule_Agent = a.Matricule_Agent
  11. AND aff.Type_Affectation = 0
  12. AND aff.Jour between 38412 38419 -- Je crois que le between est inclusif, à ce moment, c'est 38413 et 48418


 
En tout cas, même avec le distinct, ça peut pas être pire qu'avant :)

Reply

Marsh Posté le 07-03-2005 à 10:55:40    

Bon, après, je sais pas ce que c'est que cette histoire d'astreinte, tu suis les mêmes règles que celles que j'ai donné, et tu devrais pouvoir t'en tirer tout seul.
 
PS: Et EVITE les "left outeur join", c'est crade à lire, et tous les SGBD ne supportement pas (Oracle pour ne pas le citer). Donc tu fais une simple liste des tables dans ton FROM, puis tu fait des jointures sous forme de filtres bêtes et méchants. C'est infiniement plus rapide, et au moins tout le monde comprends :p. Pour faire un outer, il faut utiliser le symbole "=*" avec l'étoile du côté de "là où y'en a le plus". (avec Oracle, c'est "nomchamp = nomchamp(+)" avec le plus du côté de "là où il faut ajouter des lignes "NULL".
 
Plus facile à lire :p

Reply

Marsh Posté le 07-03-2005 à 11:04:23    

arjuna : ca ressemble fortement à la solution que je lui ai proposé plus haut, a noter que pour son 'GR' on sait pas si c'est numérique ou non niveau structure de bdd, il ne nous l'a pas donné


Message édité par Profil supprimé le 07-03-2005 à 11:05:46
Reply

Marsh Posté le 07-03-2005 à 11:08:15    


Ouais, mais là au boulot toutes les bases de donnés sont HS, alors je prend le temps d'expliquer en détail, ce que tu n'avais pas fait ;)
 
Et comme ça, il connaît aussi la solution de remplacement du IN par EXISTS (ça marche pas toujours) qui est infiniment plus conseillé, mais que personne n'utilise (les formateurs SQL et les rédacteurs de bouquins sont vraiment une bande de branquignols)

Reply

Sujets relatifs:

Leave a Replay

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