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 :

Sous requête MAX


Sujet :

Requêtes MySQL

  1. #1
    Rédacteur
    Avatar de Erakis
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2003
    Messages
    523
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Octobre 2003
    Messages : 523
    Points : 233
    Points
    233
    Par défaut Sous requête MAX
    Bonjour à tous,

    Voilà j'ai la requête suivante :
    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 ssv_Time AS ResultTime, MAX(ssv_Value) AS ResultValue
       FROM StationsSensorsValues   
       WHERE ssv_StationID = 4 AND 
                 ssv_SensorID = 28 AND 
                 ssv_Year = 2004 AND 
                 ssv_Month = 1 AND 
                 ssv_Day = 1 AND 
                 ssv_Time BETWEEN '00:00:00' AND '03:59:59'   
       GROUP BY ssv_StationID, 
                     ssv_SensorID, 
                     ssv_Year, 
                     ssv_Month, 
                     ssv_Day, 
                     HOUR( ssv_Time )
    Qui donne le résultat suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    ResultTime    ResultValue
    "00:00:00",   40.2803000000000000000000000000000
    "01:00:00",   38.4444000000000000000000000000000
    "02:00:00",   29.9121000000000000000000000000000
    "03:00:00",   31.0178000000000000000000000000000
    Maintenant, à partir de cette requête j'aimerais avoir l'heure pour laquelle le ResultValue est le plus grand (MAX).

    Donc :
    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
    SELECT MAX(ResultValue), ResultTime
    FROM 
    ( 
       SELECT ssv_Time AS ResultTime, MAX(ssv_Value) AS ResultValue
       FROM StationsSensorsValues   
       WHERE ssv_StationID = 4 AND 
                 ssv_SensorID = 28 AND 
                 ssv_Year = 2004 AND 
                 ssv_Month = 1 AND 
                 ssv_Day = 1 AND 
                 ssv_Time BETWEEN '00:00:00' AND '03:59:59'   
       GROUP BY ssv_StationID, 
                     ssv_SensorID, 
                     ssv_Year, 
                     ssv_Month, 
                     ssv_Day, 
                     HOUR( ssv_Time )
    )  AS SubTable
    GROUP BY ResultTime, ResultValue
    Voilà en italique où je n'arrive pas à tout placer pour avoir ce que je veux. C'est que je travail que quelque peut dans l'année avec SQL alors je rouille vite

    Merci à tous pour votre aide.
    Mieux vaut ne rien savoir que beaucoup savoir à moitié !
    Faite vous en pas avec la vie, personne en est sortie vivant !

  2. #2
    Membre éprouvé
    Avatar de Sivrît
    Profil pro
    Inscrit en
    Février 2006
    Messages
    953
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Février 2006
    Messages : 953
    Points : 1 249
    Points
    1 249
    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
    16
     
    SELECT ssv_Time AS ResultTime, MAX(ssv_Value) AS ResultValue
       FROM StationsSensorsValues   
       WHERE ssv_StationID = 4 AND 
                 ssv_SensorID = 28 AND 
                 ssv_Year = 2004 AND 
                 ssv_Month = 1 AND 
                 ssv_Day = 1 AND 
                 ssv_Time BETWEEN '00:00:00' AND '03:59:59'   
       GROUP BY ssv_StationID, 
                     ssv_SensorID, 
                     ssv_Year, 
                     ssv_Month, 
                     ssv_Day, 
                     HOUR( ssv_Time )
       ORDER BY ResultValue DESC LIMIT 1
    J'ai pas testé mais ça devrait être bon. Je pense que le "group by" et le "max" sont de trop. Trier par valeur et donner un temps devrait suffir et être bien plus rapide.

  3. #3
    Rédacteur
    Avatar de Erakis
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2003
    Messages
    523
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Octobre 2003
    Messages : 523
    Points : 233
    Points
    233
    Par défaut
    Merci pour ton aide.

    Cela semble très bien mais j'ai besion QUE de ssv_Time correspondant au MAX de (ssv_Value).

    Cette requête sera utilsée comme sous requête (dans un WHERE).

    Devrais-je seulement rajouté cela ?
    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
    26
    27
    28
    29
     
    SELECT * 
    FROM StationsSensorsValues
    WHERE HOUR(StationsSensorsValues.ssv_Time) = 
          HOUR(
                SELECT ResultTime FROM
                (
                   SELECT ssv_Time As ResultTime, MAX(ssv_Value) AS ResultValue
                   FROM StationsSensorsValues
                   WHERE ssv_StationID = 4 AND 
                         ssv_SensorID = 28 AND 
                         ssv_Year = 2004 AND 
                         ssv_Month = 1 AND 
                         ssv_Day = 1 AND 
                         ssv_Time BETWEEN '00:00:00' AND '03:59:59'   
                   GROUP BY ssv_StationID, 
                            ssv_SensorID, 
                            ssv_Year, 
                            ssv_Month, 
                            ssv_Day, 
                            HOUR( ssv_Time )
                   ORDER BY ResultValue DESC LIMIT 1
                ) AS SubTableTime
          ) 
          AND ssv_StationID = 4 AND 
              ssv_SensorID = 27 AND 
              ssv_Year = 2004 AND 
              ssv_Month = 1 AND 
              ssv_Day = 1 AND
    Parce qu'avec cette requête j'ai un erreur SQL et je ne vois pas du tout où est le problème
    Mieux vaut ne rien savoir que beaucoup savoir à moitié !
    Faite vous en pas avec la vie, personne en est sortie vivant !

  4. #4
    Rédacteur
    Avatar de Erakis
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2003
    Messages
    523
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Octobre 2003
    Messages : 523
    Points : 233
    Points
    233
    Par défaut
    Re-bonjour,

    Bon après maintes essais je crois que j'ai trouvé :

    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
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    UPDATE IGNORE StationsSensorsValuesAVG 
    SET ssva_Reserve_0_4 = 
    (
    
           SELECT MIN(ssv_Value) 
           FROM StationsSensorsValues 
           WHERE ssv_StationID = 4 AND      
                 ssv_SensorID = 27 AND       
                 ssv_Year = 2004 AND       
                 ssv_Month = 1 AND       
                 ssv_Day = 1 AND       
                 HOUR(StationsSensorsValues.ssv_Time) =       
                 HOUR
                 (             
                        (
                         SELECT ResultTime 
                         FROM 
                             (             
                              SELECT ssv_Time As ResultTime, AVG(ssv_Value) AS ResultValue              
                              FROM StationsSensorsValues AS SubTableResultMax
                              WHERE ssv_StationID = 4 AND                   
                                    ssv_SensorID = 28 AND                    
                                    ssv_Year = 2004 AND                    
                                    ssv_Month = 1 AND                    
                                    ssv_Day = 1 AND                    
                                    ssv_Time BETWEEN '00:00:00' AND '03:59:59'              
                              GROUP BY ssv_StationID,                       
                                       ssv_SensorID,                       
                                       ssv_Year,                       
                                       ssv_Month,                       
                                       ssv_Day,                       
                                       HOUR( ssv_Time )              
                              ORDER BY ResultValue DESC LIMIT 1
                             ) AS SubTableResultTime
                        )
                 )
           ),
    ssva_ToBeProceed = 0       
    WHERE ssva_DateEntry = '2004-01-01' AND ssva_StationID = 4;
    Mais est-ce que cette requête est optimisable ? Je parle de la petite passe avec le SELECT ResultTime FROM juste pour récupérer le Temps au lieu des deux champs ?
    Mieux vaut ne rien savoir que beaucoup savoir à moitié !
    Faite vous en pas avec la vie, personne en est sortie vivant !

  5. #5
    Membre éprouvé
    Avatar de Sivrît
    Profil pro
    Inscrit en
    Février 2006
    Messages
    953
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Février 2006
    Messages : 953
    Points : 1 249
    Points
    1 249
    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
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    UPDATE IGNORE StationsSensorsValuesAVG 
    SET ssva_Reserve_0_4 = 
    (
           SELECT MIN(ssv_Value) 
           FROM StationsSensorsValues 
           WHERE ssv_StationID = 4 AND      
                 ssv_SensorID = 27 AND       
                 ssv_Year = 2004 AND       
                 ssv_Month = 1 AND       
                 ssv_Day = 1 AND       
                 HOUR(ssv_Time) =
                        (
                              SELECT HOUR(ssv_Time)
                              FROM StationsSensorsValues
                              WHERE ssv_StationID = 4 AND                   
                                    ssv_SensorID = 28 AND                    
                                    ssv_Year = 2004 AND                    
                                    ssv_Month = 1 AND                    
                                    ssv_Day = 1 AND                    
                                    ssv_Time BETWEEN '00:00:00' AND '03:59:59'                       
                              ORDER BY ssv_Value DESC LIMIT 1
                        )
           ),
    ssva_ToBeProceed = 0       
    WHERE ssva_DateEntry = '2004-01-01' AND ssva_StationID = 4;
    Par contre si l'on a plusieurs mesures avec la valeur maximale, on ne sait pas l'heure de laquelle on récupère. Un "ORDER BY ssv_Value, ssv_Time" serait peut-être préférable pour que ce soit déterministe.

    En fait le "group" et le "max" ne servent pas, et heureusement car on ne peut pas récupérer les valeurs correspondant au max de chaque groupe (sauf si elle est constante pour tous le groupe) sans requêtes imbriqués, syntaxe cauchemardesque et performances apocalyptiques.

    On pourrait supprimer la requête interne (mais je ne sais même pas si on gagnerait en performance) et utiliser un autojointure mais je pense que c'est plus clair comme ça.

  6. #6
    Rédacteur
    Avatar de Erakis
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2003
    Messages
    523
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Octobre 2003
    Messages : 523
    Points : 233
    Points
    233
    Par défaut
    En fait je m'étais trompé, ce n'étais pas un MAX mais un AVG.
    Voir mon ancien poste que j'ai éditer. Ancien poste


    Le but de la requête est de balayer le bloc de 4h. Pour chaque tranche de 1h, je veux la moyennes des données. Ensuite à partir de ces 4 moyennes je veut l'heure de la plus élevée. Pour la même station et la même journée, je veux la valeur MIN des donnée correspondant à la même heure mais pour un autre sensor.

    Merci.
    Mieux vaut ne rien savoir que beaucoup savoir à moitié !
    Faite vous en pas avec la vie, personne en est sortie vivant !

  7. #7
    Membre éprouvé
    Avatar de Sivrît
    Profil pro
    Inscrit en
    Février 2006
    Messages
    953
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Février 2006
    Messages : 953
    Points : 1 249
    Points
    1 249
    Par défaut
    Oui... on va pas pouvoir simplifier pareil... Je ne sais pas si ça va changer quoi que ce soit, mais pour utiliser une syntaxe minimaliste :
    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
    26
    27
     
    UPDATE IGNORE StationsSensorsValuesAVG 
    SET ssva_Reserve_0_4 = 
    (
           SELECT MIN(ssv_Value) 
           FROM StationsSensorsValues 
           WHERE ssv_StationID = 4 AND      
                 ssv_SensorID = 27 AND       
                 ssv_Year = 2004 AND       
                 ssv_Month = 1 AND       
                 ssv_Day = 1 AND       
                 HOUR(ssv_Time) =       
                 (                     
                     SELECT HOUR( ssv_Time )
                     FROM StationsSensorsValues
                     WHERE ssv_StationID = 4 AND                   
                           ssv_SensorID = 28 AND                    
                           ssv_Year = 2004 AND                    
                           ssv_Month = 1 AND                    
                           ssv_Day = 1 AND                    
                           ssv_Time BETWEEN '00:00:00' AND '03:59:59'              
                     GROUP BY HOUR( ssv_Time )              
                     ORDER BY AVG(ssv_Value) DESC LIMIT 1
                 )
           ),
    ssva_ToBeProceed = 0       
    WHERE ssva_DateEntry = '2004-01-01' AND ssva_StationID = 4;
    L'allègement du "GROUP BY" ne devrait rien changer car tous les autres champs sont constants à cause du "WHERE".

    Par contre un "ORDER BY AVG(ssv_Value)" directe nécessite un MySQL assez récent.

    Je n'ai pas testé faute d'avoir la table sous la mains mais "AS SubTableResultMax" et "StationsSensorsValues.ssv_Time" doivent se raboter sans problème.

    Et au final ça fait quand même un beau bébé

  8. #8
    Rédacteur
    Avatar de Erakis
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Octobre 2003
    Messages
    523
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Octobre 2003
    Messages : 523
    Points : 233
    Points
    233
    Par défaut
    Wow ! Merci

    À première vu j'ai remarqué que la syntax est plus lisible.
    Après quelques tests sous MySQL (EXPLAIN) incluant le temps d'exécution sur 7 millions d'entrés... il n'y a pas vraiment d'amélioration.

    Toutefois, je te remerci beaucoup pour ton dévouement
    Mieux vaut ne rien savoir que beaucoup savoir à moitié !
    Faite vous en pas avec la vie, personne en est sortie vivant !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème sous-requête MAX et COUNT
    Par grafistolage dans le forum Requêtes
    Réponses: 6
    Dernier message: 06/07/2010, 09h08
  2. 2 tables, sous-requête, Max : je ne sais pas quoi utiliser
    Par Dr_shaman dans le forum Langage SQL
    Réponses: 2
    Dernier message: 02/06/2008, 17h34
  3. Réponses: 2
    Dernier message: 26/03/2008, 08h49
  4. Sous requête et max et seconde colonne
    Par Oliv- dans le forum Langage SQL
    Réponses: 1
    Dernier message: 24/10/2007, 17h17
  5. [Débutant] Requête SELECT avec max et sous-requête
    Par joefou dans le forum Langage SQL
    Réponses: 2
    Dernier message: 27/07/2005, 14h28

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