IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Requêtes MySQL Discussion :

Optimisation d'un select croisé


Sujet :

Requêtes MySQL

  1. #1
    Membre habitué
    Inscrit en
    Avril 2003
    Messages
    298
    Détails du profil
    Informations forums :
    Inscription : Avril 2003
    Messages : 298
    Points : 156
    Points
    156
    Par défaut Optimisation d'un select croisé
    Bonjour à tous,

    J'ai la table comptage qui contient environ 3500 records actuellement.

    Cette table contient les relvé mensuel pour un parc de compteur d'électricité.
    Donc à chaque relevé on ajoute un record avec la date, l'heure et les champs relevés.

    Ma requête est censée récupèrer le dernier relevé le plus récent pour chaque compteur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT cpt.id_comptage, cpt.date_lecture, cpt.numero, cpt.station, cpt.date, cpt.heure, cpt.ligne, cpt.compbrut, cpt.cptchauf, cpt.corrige1, cpt.bct, cpt.bruthf, cpt.brutbf, cpt.p, cpt.t, cpt.cf, cpt.error, cpt.defcorr, cpt.defbrut, cpt.cptelecj, cpt.cptelecn, cpt.cptelecp, cpt.energie 
    FROM lecture, comptage cpt WHERE
    lecture.client = cpt.numero AND lecture.ligne = cpt.ligne AND cpt.date_lecture = 
    (SELECT MAX(date_lecture) FROM comptage WHERE numero = cpt.numero AND ligne = cpt.ligne )
    La table lecture contient une ligne par compteur.
    Un client peut avoir plusieurs compteurs:
    client 10 ligne1, ligne2, ligne3.....

    Cette requête prend environ 5 minutes pour s'exécuter, comment faire pour optimiser ?
    WebAgency www.cpstyle.net
    BncAgency www.bncmasters.net

  2. #2
    Membre émérite Avatar de Maximil ian
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 622
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 622
    Points : 2 973
    Points
    2 973
    Par défaut
    Bonjour,

    Tu as jeté un oeil dans la FAQ ?

    http://mysql.developpez.com/faq/?pag...miser_requetes
    Pensez au bouton

  3. #3
    Membre habitué
    Inscrit en
    Avril 2003
    Messages
    298
    Détails du profil
    Informations forums :
    Inscription : Avril 2003
    Messages : 298
    Points : 156
    Points
    156
    Par défaut
    Effectivement, l'ajout d'index accélère le processus. Je ne voulais pas le faire car la base ne m'appartient pas. Je vais voir avec le client si l'utilisation d'index ne le gène pas.

    J'imaginais plutôt qu'une optimisation de ma requête était aussi possible. Est-ce le cas ou semble -t-elle correcte? J'ai mis des index sur cpt.numero, cpt.ligne, cpt.date, cpt.heure, lecture.client, lecture.ligne

    A présent il faut un quart de secondes

    Merci .
    WebAgency www.cpstyle.net
    BncAgency www.bncmasters.net

  4. #4
    Expert éminent Avatar de Mr N.
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    5 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 5 418
    Points : 6 449
    Points
    6 449
    Par défaut
    N'oublie pas de faire un ANALYZE TABLE après avoir posé ton index (et régulièrement ?)

  5. #5
    Expert éminent Avatar de Mr N.
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    5 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 5 418
    Points : 6 449
    Points
    6 449
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT cpt.id_comptage, cpt.date_lecture, cpt.numero, cpt.station, cpt.date, cpt.heure, cpt.ligne, cpt.compbrut, cpt.cptchauf, cpt.corrige1, cpt.bct, cpt.bruthf, cpt.brutbf, cpt.p, cpt.t, cpt.cf, cpt.error, cpt.defcorr, cpt.defbrut, cpt.cptelecj, cpt.cptelecn, cpt.cptelecp, cpt.energie
    FROM lecture, comptage cpt WHERE
    lecture.client = cpt.numero AND lecture.ligne = cpt.ligne
     
    ORDER BY cpt.date_lecture DESC
    LIMIT 1
    Je m'en remets au mains des pros pour savoir si c'est optimisé par rapport à ta première requète...

  6. #6
    Membre émérite Avatar de Maximil ian
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 622
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 622
    Points : 2 973
    Points
    2 973
    Par défaut
    Citation Envoyé par Mr N.
    si c'est optimisé par rapport à ta première requète...
    Indubitablement

    A ce moment-là par contre il faudrait rajouter un index sur date_lecture.
    Pensez au bouton

  7. #7
    Membre habitué
    Inscrit en
    Avril 2003
    Messages
    298
    Détails du profil
    Informations forums :
    Inscription : Avril 2003
    Messages : 298
    Points : 156
    Points
    156
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ORDER BY cpt.date, cpt.heure
    LIMIT 1
    car je viens de changer les types de ces champs en types date et time.
    Si cela fonctionne c'est parfait .

    J'ai également placé des index sur ces champs.

    Merci pour vos réponses.
    Ben ca fonctionne pas.
    Ca ne me retourne pas une ligne par client / ligne mais une seule ligne au final. Hors moi il m'en faut une part couple client / ligne distinct.

    De plus, dans ma requête initiale, comment puis-je rechercher le maximum sur les champs date et heure?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    SELECT cpt.id_comptage, cpt.date_lecture, cpt.numero, cpt.station, cpt.date, cpt.heure, cpt.ligne, cpt.compbrut, cpt.cptchauf, cpt.corrige1, cpt.bct, cpt.bruthf, cpt.brutbf, cpt.p, cpt.t, cpt.cf, cpt.error, cpt.defcorr, cpt.defbrut, cpt.cptelecj, cpt.cptelecn, cpt.cptelecp, cpt.energie 
                        FROM lecture, comptage cpt WHERE 
                        lecture.client = cpt.numero AND lecture.ligne = cpt.ligne AND cpt.date_lecture = 
                        (SELECT MAX(date) FROM comptage WHERE numero = cpt.numero AND ligne = cpt.ligne )
    WebAgency www.cpstyle.net
    BncAgency www.bncmasters.net

  8. #8
    Expert éminent Avatar de Mr N.
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    5 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 5 418
    Points : 6 449
    Points
    6 449
    Par défaut
    Citation Envoyé par WriteLN
    Ben ca fonctionne pas.
    Au temps pour moi, j'avais visiblement pas très bien cerné le besoin

  9. #9
    Membre habitué
    Inscrit en
    Avril 2003
    Messages
    298
    Détails du profil
    Informations forums :
    Inscription : Avril 2003
    Messages : 298
    Points : 156
    Points
    156
    Par défaut
    Pas grave, j'avais pas forcément bien expliqué mon besoin non plus
    WebAgency www.cpstyle.net
    BncAgency www.bncmasters.net

  10. #10
    Membre émérite Avatar de Maximil ian
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 622
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 622
    Points : 2 973
    Points
    2 973
    Par défaut
    Autant pour moi aussi, c'est vrai que ce genre de requête est impossible sans utiliser une sous-requête (ou une table temporaire).

    Pour le problème de l'heure, ça serait mieux si tout était dans une colonne au format datetime. Enfin sinon il est toujours possible d'utiliser la fonction STR_TO_DATE pour concaténer la date et l'heure...
    Pensez au bouton

  11. #11
    Membre habitué
    Inscrit en
    Avril 2003
    Messages
    298
    Détails du profil
    Informations forums :
    Inscription : Avril 2003
    Messages : 298
    Points : 156
    Points
    156
    Par défaut
    Je comprend l'utilisité de STR_TO_DATE() mais je ne vois pas comment concaténer mes deux valeurs (cpt.date, cpt.heure) dans cette fonction...

    Etant donné que mes deux champs ne sont pas de type string, comment pourrais-je les placer dans la fonction?
    WebAgency www.cpstyle.net
    BncAgency www.bncmasters.net

  12. #12
    Membre émérite Avatar de Maximil ian
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 622
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 622
    Points : 2 973
    Points
    2 973
    Par défaut
    Citation Envoyé par WriteLN
    Etant donné que mes deux champs ne sont pas de type string
    De quel type sont-ils ?
    Pensez au bouton

  13. #13
    Membre habitué
    Inscrit en
    Avril 2003
    Messages
    298
    Détails du profil
    Informations forums :
    Inscription : Avril 2003
    Messages : 298
    Points : 156
    Points
    156
    Par défaut
    date et time
    WebAgency www.cpstyle.net
    BncAgency www.bncmasters.net

  14. #14
    Membre émérite Avatar de Maximil ian
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 622
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 622
    Points : 2 973
    Points
    2 973
    Par défaut
    Avec ADDTIME(date,heure) peut-être :
    Pensez au bouton

  15. #15
    Membre habitué
    Inscrit en
    Avril 2003
    Messages
    298
    Détails du profil
    Informations forums :
    Inscription : Avril 2003
    Messages : 298
    Points : 156
    Points
    156
    Par défaut
    non il ne prend pas en compte le addTIME apparement car il me retourne TOUT les enregistrements pour ces lignes...

    Je désespère la. Si quelqu'un vois une manière rapide de faire cette recherche je lui serai reconnaisant.
    Il faudrait peut-être faire comme dans ma requête quelque poste plus haut ou je fait sous requête sur la plus grande date sous requête avec la plus grande heure mais je n'y arrive pas...

    Merci d'avance.
    WebAgency www.cpstyle.net
    BncAgency www.bncmasters.net

  16. #16
    Membre émérite Avatar de Maximil ian
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    2 622
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 2 622
    Points : 2 973
    Points
    2 973
    Par défaut
    Attends c'est bien cela que tu veux faire ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    AND ADDTIME(date,heure) =
                        (SELECT MAX(ADDTIME(date,heure)) FROM comptage WHERE numero = cpt.numero AND ligne = cpt.ligne )
    :
    Pensez au bouton

  17. #17
    Membre habitué
    Inscrit en
    Avril 2003
    Messages
    298
    Détails du profil
    Informations forums :
    Inscription : Avril 2003
    Messages : 298
    Points : 156
    Points
    156
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    SELECT cpt.id_comptage, cpt.date_lecture, cpt.numero, cpt.station, cpt.date, cpt.heure, cpt.ligne, cpt.compbrut, cpt.cptchauf, cpt.corrige1, cpt.bct, cpt.bruthf, cpt.brutbf, cpt.p, cpt.t, cpt.cf, cpt.error, cpt.defcorr, cpt.defbrut, cpt.cptelecj, cpt.cptelecn, cpt.cptelecp, cpt.energie
    FROM lecture, comptage cpt
    WHERE lecture.client = cpt.numero
    AND lecture.ligne = cpt.ligne
    AND ADDTIME(
    cpt.date, cpt.heure
    ) = (
     
    SELECT MAX( ADDTIME(
    cpt.date, cpt.heure
    ) ) 
    FROM comptage
    WHERE numero = cpt.numero
    AND ligne = cpt.ligne
    )
    Oui c'est bien cela que je veux faire si cela me permet de récupèrer les derniers relevés pour chaque compteur. Malheureusement, il me retourne tout les relevés pour tout les compteurs apparement.

    Comment faire....
    WebAgency www.cpstyle.net
    BncAgency www.bncmasters.net

  18. #18
    Membre habitué
    Inscrit en
    Avril 2003
    Messages
    298
    Détails du profil
    Informations forums :
    Inscription : Avril 2003
    Messages : 298
    Points : 156
    Points
    156
    Par défaut
    Bonjour à tous,

    Voici mes derniers résultats concernant ma requête de sélection des derniers relevés.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    SELECT date_lecture, numero, station, date, heure, ligne, compbrut, cptchauf, corrige1, bct, bruthf, brutbf, p, t, cf, error, defcorr, defbrut, cptelecj, cptelecn, cptelecp, energie
    FROM comptage t
    WHERE (
    (
    (
    t.heure
    ) = ( 
    SELECT Max( heure ) 
    FROM comptage cpt
    WHERE (
    (
    (
    cpt.date
    ) = ( 
    SELECT MAX( date ) 
    FROM comptage
    WHERE numero = cpt.numero
    AND ligne = cpt.ligne ) ) 
    )
    AND cpt.numero = t.numero
    AND cpt.ligne = t.ligne
    )
    )
    )
    ORDER BY numero
    La je récupère bien le dernier relevé selon date et heure pour TOUT les compteurs.
    Moi je voudrais recevoir le dernier relevé pour tout les compteurs se trouvant dans la table lecture en me basant sur les champs numero et ligne pour le croisement.

    Quelqu'un pourrait me dire comment faire? J'ai beaucoup de mal avec cette requête et je ne m'en sors pas vraiment.

    Merci d'avance.
    WebAgency www.cpstyle.net
    BncAgency www.bncmasters.net

  19. #19
    Membre régulier
    Profil pro
    Administrateur de base de données
    Inscrit en
    Juillet 2003
    Messages
    94
    Détails du profil
    Informations personnelles :
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Administrateur de base de données

    Informations forums :
    Inscription : Juillet 2003
    Messages : 94
    Points : 116
    Points
    116
    Par défaut
    peux tu essayer cette syntaxe

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    select C.*
    from comptage C,
    (
    SELECT numero, ligne, MAX(date_lecture) date_lecture FROM comptage
    group by numero, ligne
    ) M
    where M.numero = C.numero
    and M.ligne = C.ligne
    and M.date_lecture = C.date_lecture
    fonctionne à partir de la 4.1.x

Discussions similaires

  1. Optimisation requete avec select Imbriqué
    Par sintesi974 dans le forum Requêtes
    Réponses: 6
    Dernier message: 04/08/2010, 17h18
  2. [MySQL] Optimisation requête avec SELECT COUNT
    Par przvl dans le forum PHP & Base de données
    Réponses: 5
    Dernier message: 15/10/2008, 15h27
  3. Optimisation d'un select
    Par lodan dans le forum Requêtes
    Réponses: 1
    Dernier message: 02/07/2008, 16h14
  4. VBA Optimisation de code, Select Case et requete SQL
    Par Secco dans le forum VBA Access
    Réponses: 7
    Dernier message: 06/05/2008, 21h05
  5. Problème d'optimisation combinatoire. Enfin je crois
    Par Arpivu dans le forum Algorithmes et structures de données
    Réponses: 5
    Dernier message: 30/07/2007, 11h01

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo