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 PostgreSQL Discussion :

Analyse d'une table ligne par ligne


Sujet :

Requêtes PostgreSQL

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Janvier 2019
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Chercheur en informatique

    Informations forums :
    Inscription : Janvier 2019
    Messages : 6
    Points : 1
    Points
    1
    Par défaut Analyse d'une table ligne par ligne
    Bonjour,

    J'ai une table contenant 20 000 lignes. Cette table possède 3 champs :

    ID (identifiant unique),
    NOM (nom de la route),
    TMJA (nombre de véhicules)


    Constat: J'ai dans cette table des NOM (nom de route) identiques mais possédant un TMJA (nombre de véhicules) différents.
    Ex:
    ID=1 , NOM=A61, TMJA=20 000
    ID=2 , NOM=A61, TMJA=20 000
    ID=3 , NOM=A61, TMJA=30 000

    J'aimerai obtenir une table possédant, lorsque les NOM (nom de route) sont identiques, des TMJA (nombre de véhicules) identiques.
    Soit:
    ID=1 , NOM=A61, TMJA=20 000
    ID=2 , NOM=A61, TMJA=20 000
    ID=3 , NOM=A61_1, TMJA=30 000

    Je pensais premièrement classer ma table en fonction des NOM (ORDER BY),
    Ensuite, inspecter la table ligne par ligne en commençant à la ligne n°2: SI le NOM de la ligne2 est EGAL au NOM ligne 1 ET SI TMJA de la ligne 2 DIFFERENT TMJA de la ligne 1 ALORS changer le NOM ligne 2 SINON garder le même NOM.

    Par contre je ne sais pas comment coder cela.

    Pensez-vous que c'est la meilleure méthode ?
    Cordialement,

  2. #2
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Citation Envoyé par mattdebordeaux33 Voir le message
    Pensez-vous que c'est la meilleure méthode ?
    Non, c'est probablement une des pires, en base de données on essaie tant que faire se peut de faire un seul traitement ensembliste.
    Essayez ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    update matable as t1
       set Nom = Nom || '_' || cast((select count(distinct t2.TMJA)
                                       from matable as t2
                                      where t2.TMJA < t1.TMJA
                                        and t2.nom  = t1.nom) as varchar(10))
     where exists (select null
                     from matable as t2
                    where t2.TMJA < t1.TMJA
                      and t2.nom  = t1.nom);

  3. #3
    Membre expérimenté
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Septembre 2016
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2016
    Messages : 731
    Points : 1 416
    Points
    1 416
    Par défaut
    J'ai du mal avec votre modèle de données.
    Même s'il n'y a que 3 colonnes ça me pique un peu les yeux.

    Si j'ai bien compris le tjma correspond à : "trafic moyen journalier annuel".
    Dans la formulation même de la définition de la colonne on a bien une notion de temps, non ?
    Or le nom de la route est intemporelle.
    Comment pouvez-vous mélanger tout ça dans le même sac ? et éludant la notion de date ? et, pour finir, pour corriger une ligne par rapport à une autre sans ordre logique sinon celui du traitement.

    La "normalité" voudrait qu'il y ait dans ton système d'information au moins 2 tables.
    T_route
    Id_route
    Nom_route

    T_TJMA
    Id_tjma
    Id_route
    Position_GPS_du_relevé
    Description_des_conditions_du_relevé
    Date_début_collecte
    Date_fin_collecte
    Nombre_de_véhicules

    et encore je m'arrête là

    Donc avant de vous lancer dans cet update, merci de nous expliciter les tenants et les aboutissants du problème et particulièrement ce à quoi, in fine, votre opération va vous permette de faire.
    Le savoir est une nourriture qui exige des efforts.

  4. #4
    Nouveau Candidat au Club
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Janvier 2019
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Chercheur en informatique

    Informations forums :
    Inscription : Janvier 2019
    Messages : 6
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par Waldar Voir le message
    Non, c'est probablement une des pires, en base de données on essaie tant que faire se peut de faire un seul traitement ensembliste.
    Essayez ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    update matable as t1
       set Nom = Nom || '_' || cast((select count(distinct t2.TMJA)
                                       from matable as t2
                                      where t2.TMJA < t1.TMJA
                                        and t2.nom  = t1.nom) as varchar(10))
     where exists (select null
                     from matable as t2
                    where t2.TMJA < t1.TMJA
                      and t2.nom  = t1.nom);
    Merci à vous deux d'avoir pris le temps de me répondre !

    Merci Waldar, j'ai repris tes conseils. En effet, ça fonctionne, cependant, et je ne sais pas pourquoi, je me retrouve avec parfois de même NOM pour des TMJA différents.
    Je me suis dis que c'était à cause de "t2.tmja <t1.tmja" et j'ai essayé avec "t2.tmja <>t1.tmja" mais cela ne fonctionne pas mieux.

    J'aimerai arriver à un même NOM de route pour des TMJA, vitesses communs et des NOM de route différents si le TMJA ou la vitesse change ou si les deux change.


    en fait je voudrais lui dire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    UPDATE matable as t1
               SET nouveaunom=nom||'_'||cast (SELECT count(DISTINCT (nom,tmja, vts_vl, tissu)) FROM matable) AS t2
                                                                        WHERE (t2.tmja <> t1.tmja OR t2.vts_vl <> t1.vts_vl OR t2.tissu <> t1.tissu)
                                                                        AND t2.nom=t1.nom) AS VARCHAR(10))
              WHERE EXISTS (SELECT NULL
                                               FROM matable as t2
                                               AND t2.nom=t1.nom);
    En gros j'ai ça:

    nom|tmja|vitesse|tissu
    A620|25000|130|1
    A620|25000|130|1
    A620|25000|130|1
    A620|55000|130|1
    A620|55000|130|1
    A620|55000|90|0
    N230|15000|110|0
    N230|15000|110|0
    N230|7000|110|0
    N230|5500|800|1
    Et je veux obtenir ça:

    nouveaunom|tmja|vitesse|tissu
    A620|25000|130|1
    A620|25000|130|1
    A620|25000|130|1
    A620_1|55000|130|1
    A620_1|55000|130|1
    A620_2|55000|90|0
    N230|15000|110|0
    N230|15000|110|0
    N230_1|7000|110|0
    N230_2|5500|800|1
    En fait à chaque fois que j'ai 1 des paramètres tmja ou vitesse ou tissu qui change, le nom doit changer.

  5. #5
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Citation Envoyé par mattdebordeaux33 Voir le message
    et je ne sais pas pourquoi, je me retrouve avec parfois de même NOM pour des TMJA différents.
    Je me suis dis que c'était à cause de "t2.tmja <t1.tmja" et j'ai essayé avec "t2.tmja <>t1.tmja" mais cela ne fonctionne pas mieux.
    À mon avis vous devoir avoir des caractères blanc / invisibles dans vos noms "A60" <> "A60 " en varchar tout du moins.

    Quant à la nouvelle requête, c'est plus facile de construire une seul nombre à partir des trois.
    Faites bien attention aux bornes par contre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    update matable as t1
       set Nom = Nom || '_' || cast((select count(distinct t2.TMJA * 1e6 + t2.vitesse + t2.tissu / 100)
                                       from matable as t2
                                      where t2.nom  = t1.nom
                                        and t2.TMJA * 1e6 + t2.vitesse + t2.tissu / 100.00 < t1.TMJA * 1e6 + t1.vitesse + t1.tissu / 100.00
                                     ) as varchar(10))
     where exists (select null
                     from matable as t2
                    where t2.nom  = t1.nom
                      and t2.TMJA * 1e6 + t2.vitesse + t2.tissu / 100.00 < t1.TMJA * 1e6 + t1.vitesse + t1.tissu / 100.00);
    La numérotation sera probablement différente par rapport à ce que vous attendez, mais la règle de gestion est respectée.

  6. #6
    Membre expérimenté
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Septembre 2016
    Messages
    731
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 56
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : Conseil

    Informations forums :
    Inscription : Septembre 2016
    Messages : 731
    Points : 1 416
    Points
    1 416
    Par défaut
    Je n'adhère toujours pas au modèle de données, ni d'ailleurs au fait qu'il faille faire un update.
    Pourquoi voulez vous conserver les doublons ?

    Quoi qu'il en soit une solution serai d'utiliser rank() OVER https://www.postgresql.org/docs/9.1/...al-window.html
    pour faire apparaitre une colonne donnant un N° d'ordre identique pour tous les doublons.
    Au besoin, faire une concaténation.
    Le savoir est une nourriture qui exige des efforts.

  7. #7
    Nouveau Candidat au Club
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Janvier 2019
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Chercheur en informatique

    Informations forums :
    Inscription : Janvier 2019
    Messages : 6
    Points : 1
    Points
    1
    Par défaut
    Merci Michel.Priori,
    Et merci beaucoup Waldar !

    Çà à l'air de fonctionner cette fois ci !
    J'essaie maintenant de comprendre le code ! Je comprends que l'on concatène 3 paramètres pour créer un 4ième paramètre unique sur lequel nous ferons la distinction.

    Je ne comprends pas par contre pourquoi on multiplie par 1e6 puis en divise par 100, ni pourquoi on utilise le symbole inférieur < et non le symbole différent <> pour comparer les lignes.
    Je ne comprend pas non plus pourquoi dans la commande WHERE EXISTS on utilise un select NULL.

    Néanmoins je viens de voir que sur certaines lignes la distinction ne se fait pas. Il aurait du me changer le nom de D29_2 car les paramètres de ces 2 lignes diffèrent (cf. image ci-dessous)
    Nom : bd_trafic.png
Affichages : 160
Taille : 18,1 Ko

  8. #8
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Citation Envoyé par mattdebordeaux33 Voir le message
    Je comprends que l'on concatène 3 paramètres pour créer un 4ième paramètre unique sur lequel nous ferons la distinction.
    C'est plutôt une combinaison par addition, mais c'est l'idée.

    Citation Envoyé par mattdebordeaux33 Voir le message
    Je ne comprends pas par contre pourquoi on multiplie par 1e6 puis en divise par 100
    Justement, pour le rendre unique. Imaginons que vous avez 1 et 0 dans vos colonnes, si je les additionne ça fait le même résultat que 0 et 1.
    En gros j'assigne le premier nombre dans les millions, le second dans les unités, le dernier dans les décimales. Mais si votre nombre du milieu peut dépasser 1 million il faut décaler encore d'un zéro le premier, pour éviter d'avoir des additions potentiellement identiques.

    Citation Envoyé par mattdebordeaux33 Voir le message
    ni pourquoi on utilise le symbole inférieur < et non le symbole différent <> pour comparer les lignes.
    C'est ce qui va permettre de "trier" les lignes, je comptabilise celles qui ont le même nom et des valeurs différentes sur (tjma, vitesse, tissu).

    Citation Envoyé par mattdebordeaux33 Voir le message
    Je ne comprend pas non plus pourquoi dans la commande WHERE EXISTS on utilise un select NULL.
    Le where exists étant un test d'existence, le select associé n'est pas évalué - il est quand même syntaxiquement validé. Vous pouvez d'ailleurs écrire where exists (select 1/0 ...) !
    Je préfère null pour afficher cette non-évaluation, mais il n'y a pas de bonne pratique, on croise aussi souvent where exists (select 1 ...) ou where exists (select * ...).

    Citation Envoyé par mattdebordeaux33 Voir le message
    Néanmoins je viens de voir que sur certaines lignes la distinction ne se fait pas. Il aurait du me changer le nom de D29_2 car les paramètres de ces 2 lignes diffèrent (cf. image ci-dessous)
    C'est étrange, je ne vois pas de raison.
    Pouvez-vous publier toutes les données relatives au nom D29 ?

  9. #9
    Nouveau Candidat au Club
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Janvier 2019
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Chercheur en informatique

    Informations forums :
    Inscription : Janvier 2019
    Messages : 6
    Points : 1
    Points
    1
    Par défaut
    Merci pour ces explications !!

    Et bien toutes les données relatives au D29 sont affichées car c'est trié par nom. Mais voici une vision plus large avec le champ nomm qui est utilisé pour l'update.
    J'ai la même chose pour D3_2 et D3_8 car même si le tmja est le même , soit le pramaètre vitesse diffère soit le paramètre allure diffère.
    voici le code également:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    update public.vue_modif_donnees as t1
       set nomm2 = nomm || '_' || cast((select count(distinct t2.tmja * 1e6 + t2.vts_vl + t2.tissu / 100)
                                       from public.vue_modif_donnees as t2
                                      where t2.nomm  = t1.nomm
                                        and t2.tmja * 1e6 + t2.vts_vl + t2.tissu / 100.00 < t1.tmja * 1e6 + t1.vts_vl + t1.tissu / 100.00
                                     ) as varchar(10))
     where exists (select null
                     from public.vue_modif_donnees as t2
                    where t2.nomm  = t1.nomm
                      and t2.tmja * 1e6 + t2.vts_vl + t2.tissu / 100.00 < t1.tmja * 1e6 + t1.vts_vl + t1.tissu / 100.00);
    Nom : bd2.jpg
Affichages : 140
Taille : 181,1 Ko

  10. #10
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    J'ai fait le test ici et je n'ai pas le même résultat :
    http://sqlfiddle.com/#!17/b98ee/1/0

  11. #11
    Nouveau Candidat au Club
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Janvier 2019
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Chercheur en informatique

    Informations forums :
    Inscription : Janvier 2019
    Messages : 6
    Points : 1
    Points
    1
    Par défaut
    J'ai relancé et j'ai toujours la même chose.

    Cela peut il venir du format de mon champ tjma numeric ? Certains n'ont pas de ".0000000"

  12. #12
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Customer Success Manager @Vertica
    Inscrit en
    Septembre 2008
    Messages
    8 452
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Customer Success Manager @Vertica
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 452
    Points : 17 820
    Points
    17 820
    Par défaut
    Quel est le code de la vue ?

  13. #13
    Nouveau Candidat au Club
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Janvier 2019
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Chercheur en informatique

    Informations forums :
    Inscription : Janvier 2019
    Messages : 6
    Points : 1
    Points
    1
    Par défaut
    çà a l'air de fonctionner finalement. J'ai juste re créée 2 colonnes tmja et vts_vl en format numeric

    Étonnamment le résultat est différent qu'auparavant avec une numérotation/incrémentation qui repart à zéro quand le nom de route change.

    Nom : bd3.jpg
Affichages : 113
Taille : 114,4 Ko

Discussions similaires

  1. Lire une table ligne par ligne
    Par Deciprog dans le forum Macro
    Réponses: 17
    Dernier message: 15/02/2010, 09h13
  2. Réponses: 2
    Dernier message: 08/09/2009, 11h57
  3. lire une table ligne par ligne
    Par Damien69 dans le forum Persistance des données
    Réponses: 0
    Dernier message: 04/06/2009, 14h57
  4. [WD10] remplir une table ligne par ligne
    Par clades dans le forum WinDev
    Réponses: 1
    Dernier message: 05/07/2007, 20h59
  5. aditionner les champs d'une table ligne par ligne
    Par bertrand_declerck dans le forum Bases de données
    Réponses: 3
    Dernier message: 09/08/2005, 08h38

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