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

Python Discussion :

Jointure de tables python


Sujet :

Python

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    58
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 58
    Par défaut Jointure de tables python
    Bonjour,
    sous python 2.5, j'ai lu des tables .csv avec en en-tête les noms de variables.
    Chaque table a une variable "clé primaire".
    J'ai besoin de faire des jointures entre ces tables comme on le ferait sous SQL, mais uniquement sous python.
    Quel est le moyen le + simple et optimisé ?
    Y-a-t'il un module spécifique à importer ?
    Merci.

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    58
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 58
    Par défaut
    Par ex:
    j'ai 2 tables représentées sous python par 2 listes de listes:
    glaces=[[id_glace,nb_boules,parfum],[1,2,1],[2,1,5],...]
    desc_parfums=[[id_parfum,desc],[1,'vanille'],[2,'choco'],[3,'fraise'],[4,'cara'],[5,'miel'],...]
    je veux obtenir la table donnant les valeurs de id_glace,nb_boules,parfum,desc après la jointure entre parfum et id_parfum.
    Peut-on créer une classe avec les modèles glaces, parfum, etc ?

  3. #3
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Je ne connais pas de fonctions qui font cela tout seul avec les listes, mais voilà comment je ferais:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    glaces = [[1,2,1],[2,1,5],[3,1,4]]
    desc_parfums=[[1,'vanille'],[2,'choco'],[3,'fraise'],[4,'cara'],[5,'miel']]
     
    table = []
    for glace, boules, parfum in glaces:
        for id_parfum, desc in desc_parfums:
            if id_parfum==parfum:
                break
        table.append([glace, boules, parfum, desc])
     
    print table
    [[1, 2, 1, 'vanille'], [2, 1, 5, 'miel'], [3, 1, 4, 'cara']]
    Cela suppose qu'on est sûr qu'il existe une correspondance parfum->id_parfum.

    Tyrtamos

  4. #4
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    Le passage de tyrtamos m'ayant permis d'être un peu plus sûr de ce que tu demandes, je proposes

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    glaces = [[1,2,1],[2,1,5],[3,1,4]]
    desc_parfums=[[1,'vanille'],[2,'choco'],[3,'fraise'],[4,'cara'],[5,'miel']]
     
    d = dict(desc_parfums)
    [ u.append(d[u[2]]) for u in glaces ]
    Pour des considérations intéressantes sur les dictionnaires, suivre les liens suivants

    http://www.python.org/doc/2.5.2/lib/...g.html#l2h-290

    http://www.biologeek.com/bonnes-prat...stuces-python/

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    58
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 58
    Par défaut
    Merci pour ces idées !
    Moi, je me penchais sur :
    http://www.django-fr.org/documentation/model-api/
    django utilisable pour assimiler mes tables de données comme des tables d'une base de données, avec clés primaires, déclaration des types de champs, etc...
    C'est peut-être impossible, vu que j'importe des tables .csv plates.
    A votre avis ?

  6. #6
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Tout dépend de ton projet: sa nature, sa taille, sa criticité, etc...

    Django est un outil pour le web. Il existe d'ailleurs un forum spécialisé sur ce site.

    Si tu as une application complexe de base de données relationnelles, mysql est un bon outil. En plus d'être utilisable sur le web, il s'installe sans problème sur un ordinateur isolé, et s'utilise dans une logique fournisseur-client.

    Une solution un peu plus simple, c'est sqlite3 qui est intégré dans Python à partir de la 2.5. Il n'est plus dans la logique fournisseur-client, et il a quelques limitations dans les instructions sql, mais il est plus simple que mysql (par exemple, les droits ne sont pas gérés).

    Et comme ça m'intéressait aussi, j'ai transformé ton pb avec sqlite3 pour voir ce que ça donne, et manifestement, ça marche:

    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
     
    #!/usr/bin/python
    # -*- coding: utf-8 -*-
     
    import os
    import sqlite3
     
    ##############################################################################
    glaces = [[1,2,1],[2,1,5],[3,1,4]]
    desc_parfums=[[1,'vanille'],[2,'choco'],[3,'fraise'],[4,'cara'],[5,'miel']]
    """
    objectif:
    table = [[1, 2, 1, 'vanille'], [2, 1, 5, 'miel'], [3, 1, 4, 'cara']]
    """
     
    # ============================================================================
    # creation de la base: CREATE DATABASE test
     
    # repertoire dans lequel se trouvera la base de donnees
    rep = r"C:\Python25\Pydev\test\sql\bdr\test"
     
    # nom de la base de donnes: au depart, ce n'est qu'un simple fichier vide (0 octet)
    base = r"test.bdr"
     
    # connexion à la base de donnees
    bdr = sqlite3.connect(os.path.join(rep,base))
     
    # obtention d'un curseur
    cur = bdr.cursor()
     
    # ============================================================================
    # creation de la table glaces
    cur.execute('CREATE TABLE glaces(elem1 INTEGER, elem2 INTEGER, elem3 INTEGER)')
     
    # remplissage de la table glaces à partir de la liste glaces
    for i1, i2, i3 in glaces:
        cur.execute('INSERT INTO glaces VALUES(' + str(i1) + ',' + str(i2) + ',' + str(i3) + ')')
     
    # verification: affichage du contenu de la table glaces:
    cur.execute('SELECT * from glaces')
    print
    for ligne in cur.fetchall():
        print ligne
     
    # ============================================================================
    # creation de la table desc_parfums
    cur.execute('CREATE TABLE desc_parfums(elem INTEGER, desc TEXT(12))')
     
    # remplissage de la table desc_parfums à partir de la liste desc_parfums
    for i, x in desc_parfums:
        cur.execute('INSERT INTO desc_parfums VALUES(' + str(i) + ',"' + x + '")')
     
    # verification: affichage du contenu de la table glaces:
    cur.execute('SELECT * from desc_parfums')
    print
    for ligne in cur.fetchall():
        print ligne
     
    # ============================================================================
    # jointure gauche entre les 2 tables
    cur.execute('SELECT elem1, elem2, elem3, desc FROM glaces LEFT OUTER JOIN desc_parfums ON glaces.elem3=desc_parfums.elem')
     
    # recuperation du resultat de la jointure:
    table = cur.fetchall()
     
    # affichage du resultat
    print
    for ligne in table:
        print ligne
     
    # ============================================================================
    # fermeture du curseur
    cur.close()
    # fermeture de la base
    bdr.close()
    Pour essayer chez toi, remplace rep par un répertoire existant, et fabrique dans ce répertoire un fichier vide appelé 'test.bdr'.

    Ce qui affiche:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    (1, 2, 1)
    (2, 1, 5)
    (3, 1, 4)
     
    (1, u'vanille')
    (2, u'choco')
    (3, u'fraise')
    (4, u'cara')
    (5, u'miel')
     
    (1, 2, 1, u'vanille')
    (2, 1, 5, u'miel')
    (3, 1, 4, u'cara')
    On voit que la jointure a bien été obtenue!

    Mais bon. Si tu n'as que quelques dizaines d'éléments sans accès multiples en réseaux, les solutions citées dans les précédents messages sont peut-être suffisantes...

    Tyrtamos

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    58
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 58
    Par défaut
    Bonjour,
    merci pour ces explications et solutions.
    Pour l'instant, je transforme des tables (>100000 lignes) en dictionnaires dont les clés (une valeur ou un tuple) représentent les clés primaires.
    Par dict[key][var_voulue], j'appelle une certaine valeur de ma variable.
    C'est très limité, normal vu que je pars de fichiers .csv et non de bdd.
    Et c'est très lent !
    Tyrtamos, ta modélisation en bdd avec sqlite est pratique, peut-être + fonctionnelle et rapide.
    Je vais la tester.

  8. #8
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Attends! J'ai plus simple.

    Je ne me rendais pas compte que tu manipulais des fichiers aussi grands. Dans ce cas, convertir tes 2 listes dans une autre structure de données pour avoir la jointure devient très coûteux en temps.

    Je pars du principe que:

    1)- tu as déjà les 2 fichiers sous forme de listes:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    glaces = [[1,2,1],[2,1,5],[3,1,4]]
    desc_parfums=[[1,'vanille'],[2,'choco'],[3,'fraise'],[4,'cara'],[5,'miel']]
    2)-le 1er élément de chaque sous-liste de desc_parfums (comme le 3 de [3,'fraise']) va effectivement dans l'ordre des nombres croissants sans trou: 1, 2, 3, ...

    Alors, on peut retrouver facilement cette sous-liste connaissant son 1er élément. Par exemple, pour la valeur 3, la sous-liste [3,'fraise'] se trouve à l'indice 3-1=2 de la liste desc_parfums, et donc sa valeur 'fraise' se trouve à desc_parfums[3-1][1].

    Dans ce cas, la jointure est super simple et probablement très rapide:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    table = []
    for x, y, z in glaces:
        table.append([x, y, z, desc_parfums[z-1][1]])
    Et on peut même le faire en une seule ligne:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    table = [[x, y, z, desc_parfums[z-1][1]] for x, y, z in glaces]
    Le résultat est, bien sûr, la même chose qu'avant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    print table
    [[1, 2, 1, 'vanille'], [2, 1, 5, 'miel'], [3, 1, 4, 'cara']]

    Plus simple que ça, t'auras du mal

    Tyrtamos

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    58
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 58
    Par défaut
    Ouais, une autre solution possible, mais qui suppose que mes clés valent 1, 2, ..., n.
    Alors qu'avec un dictionnaire, ou sqlite, la valeur des clés n'importe pas.

  10. #10
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Si les clés peuvent être quelconques, il y a encore une solution un peu plus complexe, mais qui reste rapide:

    - trier la liste desc_parfums en fonction de la clé
    - trouver la clé avec une recherche par dichotomie

    Si tu n'y arrives pas avec les autres solutions, dis-le pour que je développe cette solution.

    Tyrtamos

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2009
    Messages
    58
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2009
    Messages : 58
    Par défaut
    En fait, j'ai pour l'instant une fonction qui sépare en 2 listes les clés des valeurs associées, à partir d'une liste de liste data initiale.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    keys=[]
    val=[]
    for i in range(0,len(data)):
        if len(ind_k)>1:
            keys.append(tuple([data[i][j] for j in ind_k]))
        else:
            for j in ind_k:
                keys.append(data[i][j])
        val.append([data[i][j] for j in index])
    selon qu'on a des clés ou tuple de clés. Ensuite:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    data_map=dict(zip(keys,val))
    Ca marche.
    Si j'ai un autre soucis, je repasserai.

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

Discussions similaires

  1. Jointure de table avec Interbase
    Par ada_b dans le forum InterBase
    Réponses: 21
    Dernier message: 12/05/2010, 19h52
  2. Réponses: 7
    Dernier message: 10/02/2005, 00h13
  3. [FB1.5]Vue avec jointure sur tables ?
    Par Sitting Bull dans le forum SQL
    Réponses: 2
    Dernier message: 07/12/2004, 17h07
  4. jointure sur table et procedure stocké
    Par pram dans le forum SQL
    Réponses: 3
    Dernier message: 18/11/2004, 21h56
  5. requete(jointure 2 tables) qui marche pas
    Par DaxTaz dans le forum Langage SQL
    Réponses: 3
    Dernier message: 01/06/2004, 17h50

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