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 :

Requête de parcours d'une liste vers le haut et récupération d'un élément n-1


Sujet :

Requêtes MySQL

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2017
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2017
    Messages : 2
    Points : 1
    Points
    1
    Par défaut Requête de parcours d'une liste vers le haut et récupération d'un élément n-1
    Bonjour,

    Tout d’abord, j’espère poster au bon endroit ! Et désolé si le titre est peu explicite, je ne sais trop comment résumer le sujet.
    Je suis confronté à un jeu de données sur lequel j’aimerais appliquer un traitement particulier sur certaines lignes où il manque une information.

    Voici tout d’abord rapidement l’exposé du problème, que je simplifie. Je pars d’une table row_data qui contient 4 colonnes :
    - Colonne 1 : timestamp, je m’en fiche un peu pour l’instant
    - Colonne 2 : ID, qui identifie un objet que l’on va retrouver une ou plusieurs fois dans ma liste
    - Colonne 3 : Action, qui identifie un type d’action. Ici pour simplifier il n’y a que 2 actions possibles : MOVE et STOP (en réalité il y’en a beaucoup plus)
    - Colonne 4 : Value, une valeur mesurée sous forme de chaine de caractère

    Pour les actions STOP, et seulement pour cette action, aucune valeur n’est mesurée. Mon but serait de pouvoir retrouver, pour ces actions particulières, la dernière valeur mesurée associée à l’ID.
    Dans l’exemple ci-dessous, on voit un STOP à la ligne 14 pour l’ID 444182. La dernière action vue pour cet ID est en ligne 6 : A2911311.

    Nom : row_data.png
Affichages : 147
Taille : 20,3 Ko

    Ainsi je cherche à extraire de cette table brute une table ne contenant que les lignes correspondant aux actions de type STOP mais auxquelles j’ajouterai les dernières valeurs lues dans la table row data sur la base de l’ID.

    Nom : result.png
Affichages : 144
Taille : 12,2 Ko

    J’ai déjà réalisé l’exercice sous Excel en utilisant la fonction d’index, mais le problème est que ce n’est pas du tout adapté au volume de données que j’ai à traiter (100000 lignes pour commencer).

    C’est pourquoi je me tourne vers le SQL, auquel j’essaie de m’initier un peu en urgence…
    Dans le code ci-dessous, comment puis-je m’y prendre pour récupérer le dernier « value » lue pour chaque ID ? Existe-t-il une fonction dédiée à ce que je veux faire ? C'est-à-dire recherche vers le haut et récupération de la première ligne vue sur la base de l’ID ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    drop table if exists result;
    create table result (time integer(10),`ID` integer(10), Start_action varchar(10),`Last_Value` varchar(10));
     
    insert into result
    	select
    		timestamp as time,
    		ID as ID,
    		Action as Start_action,
    		Value as Last_Value 
    	from test_algo.row_data_algo
    where Action LIKE 'STOP'
     
    group by time, ID, Start_action, Last_Value
    Ou bien faut-il que je parcours la table depuis le début avec une condition de type ID = IDrecherché et je crée un vecteur contenant les numéros de lignes associés, puis je demande de lire la valeur de la dernière ligne de cette table ?

    Merci par avance pour votre aide !

  2. #2
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 761
    Points : 52 547
    Points
    52 547
    Billets dans le blog
    5
    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
    SELECT T1.*
    FROM   T AS T0
           JOIN (SELECT ID, MAX(timestamp) AS ts_max
    			 FROM   T AS TX
    			 WHERE  EXISTS(SELECT *
    						   FROM   T 
    						   WHERE  T.action = 'STOP'
    						     AND  T.ID =TX.ID
    							 AND  T.timestamp > TX.timestamp)
    			 GROUP  BY ID) AS T1
    			 ON T0.ID = T1.ID
    			 AND T0.timestamp = T1.ts_max
    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  3. #3
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2017
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Mars 2017
    Messages : 2
    Points : 1
    Points
    1
    Par défaut
    Bonjour SQLpro,

    Merci beaucoup pour ta réponse !
    Excuse-moi mais je ne suis pas sûr d’arriver à te suivre.

    Déjà je bloque un peu sur les deux premières lignes (oui je pars de loin !) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    SELECT T1.*
    FROM   row_data_algo AS T0
    J’ai commencé par appliquer ce code dans une nouvelle requête, en remplaçant simplement le « T » par ma table brute.
    Cela me renvoi un tableau contenant pour chaque ID, le timestamp qui correspond au MOVE qui précède le dernier STOP sur toute la liste. (et déjà je te dis encore un grand merci :-) )
    Toutefois il me faut faire cela non pas uniquement pour le dernier STOP, mais pour tous les STOP de la liste, et qui plus est récupérer la valeur Value associée au MOVE qui précède.
    Le but final est de partir ensuite de la table ne contenant plus que les STOP et d’étudier le last_value.

    Excuse mon faible niveau, mais comment dois-je incorporer ce code dans le mien pour que, au lieu du simple « value as Last_Value », je récupère directement la dernière valeur lue à chaque fois que je rencontre un STOP ?

    Pour revenir sur ton code, je vois 4 tables : T, Tx, T0, T1

    De ce que je comprends,
    - T doit être directement le nom de la table de données brute que j’appelle « row_data_algo »
    - T0 est une table temporaire qui sert à parcourir T ? Je n'arrive pas bien à voir à quoi elle sert
    - Tx sert à renvoyer un couple ID et son Timestamp max dans la table row_data
    - T1 sert à repérer le « STOP » qui vient depuis timestamp_max ?

    Je vois ensuite à peu près l’idée de la jointure, qui permet au final, pour chaque ID, d’extraire de la table T0 la ligne complète (donc avec la valeur qui m’intéresse) à timestamp = ts_max qui est stockée dans T1

    Merci encore d’avance, et bonne soirée !

  4. #4
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 761
    Points : 52 547
    Points
    52 547
    Billets dans le blog
    5
    Par défaut
    Je ne vais pas vous donner un cours particulier de SQL en ligne ! La requête postée est en langage SQL standard et fait appel à des choses bien connues qui fonctionne même sur des SGBD très limités comme MySQmerde...

    Il me semble plus simple que vous appreniez ce langage...

    Pour ce faire, vous disposez des pages que j'ai écrite ici même : http://sqlpro.developpez.com/
    Section "le SQL de A à Z"
    Si vous voulez quelque chose de plus approfondis, il y a mes livres :Nom : Couverture SQL Synthex 4e ed - 500.jpg
Affichages : 125
Taille : 77,8 Ko

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  5. #5
    Expert éminent sénior Avatar de Artemus24
    Homme Profil pro
    Agent secret au service du président Ulysses S. Grant !
    Inscrit en
    Février 2011
    Messages
    6 378
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Agent secret au service du président Ulysses S. Grant !
    Secteur : Finance

    Informations forums :
    Inscription : Février 2011
    Messages : 6 378
    Points : 19 055
    Points
    19 055
    Par défaut
    Salut à tous.

    Citation Envoyé par Guardi_Guedj
    Colonne 1 : timestamp, je m’en fiche un peu pour l’instant
    Votre colonne n'est pas un timestamp, mais une colonne auto incrémentée.
    Un timestamp c'est ceci : "2017-03-17 19:15:23.123456", sur 26 caractères à l'affichage.

    Et non, vous ne devez pas vous en foutre car elle va servir à sélectionner le dernier tuple pour l'action "STOP".

    Citation Envoyé par Guardi_Guedj
    Mon but serait de pouvoir retrouver, pour ces actions particulières, la dernière valeur mesurée associée à l’ID.
    La dernière valeur mesurée est donc celle ayant le timestamp le plus grand !

    Ce qui donne :
    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
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    --------------
    SET AUTOCOMMIT = 0
    --------------
     
    --------------
    START TRANSACTION
    --------------
     
    --------------
    DROP DATABASE IF EXISTS `base`
    --------------
     
    --------------
    CREATE DATABASE `base`
        DEFAULT CHARACTER SET `latin1`
        DEFAULT COLLATE       `latin1_general_ci`
    --------------
     
    --------------
    DROP TABLE IF EXISTS `test`
    --------------
     
    --------------
    CREATE TABLE `test`
    ( `timestamp`    integer unsigned  not null auto_increment primary key,
      `id`           integer unsigned  not null,
      `action`       char(04)          not null,
      `value`        char(08)          not null
     ) ENGINE=InnoDB
      DEFAULT CHARSET=`latin1` COLLATE=`latin1_general_ci`
      ROW_FORMAT=COMPRESSED
    --------------
     
    --------------
    insert into `test` (`id`,`action`,`value`) values
      (635228, 'MOVE', 'A1913221'),
      (444182, 'MOVE', 'A2512411'),
      (444182, 'MOVE', 'A2911311'),
      (444182, 'STOP', ''),
      (782314, 'MOVE', 'A1913121'),
      (444182, 'MOVE', 'A3311211')
    --------------
     
    --------------
    select * from `test`
    --------------
     
    +-----------+--------+--------+----------+
    | timestamp | id     | action | value    |
    +-----------+--------+--------+----------+
    |         1 | 635228 | MOVE   | A1913221 |
    |         2 | 444182 | MOVE   | A2512411 |
    |         3 | 444182 | MOVE   | A2911311 |
    |         4 | 444182 | STOP   |          |
    |         5 | 782314 | MOVE   | A1913121 |
    |         6 | 444182 | MOVE   | A3311211 |
    +-----------+--------+--------+----------+
    --------------
    select      t1.timestamp,
                t1.id,
                t1.action,
                t2.value
          from  test      as t1
     
    inner join  test      as t2
            on  t2.id     = t1.id
           and  t2.action = 'MOVE'
     
         where  t1.action = 'STOP'
           and  t2.timestamp = (select max(timestamp) from test as t3 where t3.id = t2.id and t3.action = 'MOVE')
    --------------
     
    +-----------+--------+--------+----------+
    | timestamp | id     | action | value    |
    +-----------+--------+--------+----------+
    |         4 | 444182 | STOP   | A3311211 |
    +-----------+--------+--------+----------+
    --------------
    COMMIT
    --------------
     
    --------------
    SET AUTOCOMMIT = 1
    --------------
     
    Appuyez sur une touche pour continuer...
    @+
    Si vous êtes de mon aide, vous pouvez cliquer sur .
    Mon site : http://www.jcz.fr

Discussions similaires

  1. Problème requête d'affichage d'une liste
    Par mLk92 dans le forum Requêtes
    Réponses: 3
    Dernier message: 14/01/2007, 11h17
  2. Export d'une liste vers excel
    Par fsautejeau dans le forum Access
    Réponses: 22
    Dernier message: 31/08/2006, 14h45
  3. Réponses: 4
    Dernier message: 30/08/2006, 12h17
  4. Basuler un élément d'une liste vers une autre liste
    Par Daniel MOREAU dans le forum Access
    Réponses: 1
    Dernier message: 13/04/2006, 22h55
  5. Réponses: 3
    Dernier message: 25/04/2005, 15h26

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