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

Langage SQL Discussion :

[MySQL] Chargement de table intelligent, problème de jointure.


Sujet :

Langage SQL

  1. #1
    Membre expérimenté
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    1 349
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Avril 2006
    Messages : 1 349
    Points : 1 460
    Points
    1 460
    Par défaut [MySQL] Chargement de table intelligent, problème de jointure.
    Salut!
    Vous sentez cette odeure?...
    Ca sent la requête pourrie et les neuronnes cramés.
    J'en peu plus je post.

    Donc je me prend actuellement la tête sur un porblème de chargement de table (quotidien) sous MySQL. Le chargement est un peu spécifique :



    Il s'agit de mettre à jours la table1 (t1)avec les données de la table3 (t3).
    Comme vous pouvez le constater, ces deux tables sont jointables par le biais d'une 3ième: la table 2 (t2)
    Pour ajouter un peu de piment, le moteur MyISAM m'interdit les clés étrangères. On pourrait opter pour la méthode bourrine, c'est à dire vider t1 pour la recharger ensuite, mais il nous faut concerver l'identifiant numérique de t1 (auto_increment...).

    Pour réaliser le chargement, j'ai donc identifié quelques étapes :

    - Supprimer les enregistrements t1 orphelins (id_num2* t1 n'est égal à aucun id_num2 t2) pour simuler la clé étrangère.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    "DELETE FROM t1 WHERE `id_num2*` NOT IN (SELECT id_num2 FROM t2);
    - Supprimer les enregistrements t1 qui ne correspondent plus aux enregistrements t3
    Là je bloque, j'ai passé pas mal de temps à essayé divers trucs avec des jointures (de tout types ) mais ca donne pas grand chose.

    - Ajouter les enregistrements de t3 qui ne figurent pas dans t1:
    Là ca marche (presque).

    - Updater les enregistrements existants de t1 avec ceux de t3.
    Je bloque aussi...

    En plus, j'ai simplifié: En effet, la table 3 n'a pas de clé primaire. Il faut en constituer une avec la concaténation de id_char et data3, pour l'utiliser dans les jointures...
    le schéma donnerai plus ceci:



    La jointure entre t1 et t2 permet la concaténation des champs id_char* t2 et data3 t1 . Cette concaténation permet ensuite la jointure entre t2 et t3 ...

    Le casse tête quoi. Donc j'y travaille et vous tiens au courant, toute aide serai la bienvenue, ce truc dépasse ma connaissance du SQL et je sature

    Merci!

  2. #2
    Membre expérimenté
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    1 349
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Avril 2006
    Messages : 1 349
    Points : 1 460
    Points
    1 460
    Par défaut
    Voici ma requete d'ajout qui fonctionne presque. L'idée est donc d'ajouter tous les enregistrements de t3 ne figurant pas dans t1, dans t1.

    A l'execution, (avec t1 vide), j'ajoute 14066 enregistrements alors que la table t3 n'en contient que 14005.
    Je pense que le problème vient de la jointure entre (t1/t2) et t3. Elle devrai plutot se faire sur la concaténation, et non sur les id...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    INSERT INTO table1 t1 (`id_num2*`, `data1`, `data2`, `data3`) (
     
    				SELECT t2.id_num2, t3.data1, t3.data2, t3.data3
    				FROM table3 t3
    				INNER JOIN table2 t2 ON t3.`id_char`=t2.`id_char*`
    				WHERE CONCAT(t3.data3,t3.`id_char`) NOT IN (
    				SELECT CONCAT(t1.data3,t3.id_char)
    				FROM table1 t1 INNER JOIN table2 t2 ON t1.`id_num2*`=t2.id_num2))

  3. #3
    Expert éminent sénior
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 801
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 61
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 801
    Points : 34 063
    Points
    34 063
    Billets dans le blog
    14
    Par défaut
    Il s'agit de mettre à jours la table1 (t1)avec les données de la table3 (t3).
    A quoi sert la table t2 ?
    Et pourquoi a t-elle plus de lignes que t3 ?
    Il me semble qu'on peut directement alimenter t1 à partir de t3 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    INSERT INTO table1 t1 (data1, data2, data3) 
    SELECT t3.data1, t3.data2, t3.data3
    FROM t3
    WHERE NOT EXISTS (
      SELECT *
      FROM t1
      WHERE t1.data1 = t3.data1
        AND t1.data2 = t3.data2
        AND t1.data3 = t3.data3
    )

  4. #4
    Membre expérimenté
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    1 349
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Avril 2006
    Messages : 1 349
    Points : 1 460
    Points
    1 460
    Par défaut
    La table t2 permet, lors du chargement de la table t1 par t3, de compléter ce dernier avec le champ id_num2*.

    En effet, l'ojectif final est une jointure entre t1 et t2 sur id_num2. La table t3 (table tampon, loaddatainfile) ne peux pas connaitre cet id_num2 (id auto incrémenté) et qui est pourtant nécessaire dans dans t1 pour chaque enregistrement.

    Cela signifie que pour le chargement, la jointure t3 => t1 passe par la concaténation de id_char->data3, jointé sur t2 pour récupérer l'id_num2 associé.

    Une fois le chargement effectué (t3 devenu inutile), la jointure t1 -> t2 se fait proprement sur l'id_num2.

    t2 a plus de lignes que t3 car il ne s'agit pas des mêmes infos:
    par exemple (tout a fait au hazard):
    t2=table des dslam;
    t1=table des liens appartenant aux dslam;
    t3=table tampon des liens appartenant aux dslam;

    On peut avoir des dslam sans lien (d'ou nb_enr t3 > nb_enr t2).
    De même qu'on peut avoir des dslam avec plusieurs liens (d'ou t1 à part avec clé étrangère pour correspondance avec t2)...

    Voila j'espère que ca précise... Je vais faire des tests ce week end sur une base réduite (mes requetes prennent 10min a chaque fois là).

    Faut que je trouve comment faire, j'ai plein d'autres tables qui vont se charger sur ce modèle...

  5. #5
    Membre expérimenté
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    1 349
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Avril 2006
    Messages : 1 349
    Points : 1 460
    Points
    1 460
    Par défaut
    Bien, je crois que j'ai résolu le problème, à force de tests.

    Donc ma solution donne ça:
    - Supprimer les enregistrements orphelins :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    DELETE t1 FROM table1 t1 WHERE t1.`id_num*` NOT IN (SELECT t2.id_num2 FROM table2 t2);
    - Supprimer les enregistrements de t1 ne correspondant plus aux enregistrement de t3 (critère: concaténation de t3.id_char et t3.data3, qui doit correspondre à concaténation de t2.id_char* et t1.data3) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    DELETE t1 FROM table1 t1 INNER JOIN table2 t2 ON t1.`id_num2*`=t2.id_num2 WHERE concat(t1.data3,t2.id_char*) NOT IN (SELECT concat(t3.data3,t3.id_char) FROM table3 t3);
    - Ajouter les enregistrements de t3 qui ne figurent pas dans t1:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    INSERT INTO table1 (`id_num2*`, `data1`, `data2`, `data3`) (
    SELECT t2.id_char, t3.data1, t3.data2, t3.data3
    FROM table3 t3
    INNER JOIN table2 t2 ON t3.id_char*=t2.id_char
    WHERE CONCAT(t3.data3,t3.id_char) NOT IN (
    SELECT CONCAT(t1.data3,t2.id_char*)
    FROM table1 t1 INNER JOIN table2 t2 ON t1.`id_num2*`=t2.id_num2));
    - Updater tous les enregistrements existants de t1 avec ceux de t3:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    update t1 from (table1 t1 INNER JOIN table2 t2 ON t1.`id_num2*`=t2.id_num2)
    inner join table3 t3 on concat(t3.data3,t3.id_char)=concat(t1.data3,t2.id_char*)
    set t1.data1=t3.data1 ,t1.data2=t3.data2;
    Voila c'est donc la zone, en plus les jointures sur les concat c'est lent au possible.
    Si par hazard quelqu'un prend le temps d'y réfléchir et voit mieux que les requetes ci dessus pour atteindre les objectifs souhaités, je l'encourage a nous faire part de sa solution.
    En attendant le laisse celle ci des fois que quelqu'un ait le même problème.

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

Discussions similaires

  1. Réponses: 6
    Dernier message: 31/03/2006, 18h05
  2. Problème de jointure entre 2 tables Access
    Par MITCH31 dans le forum VBA Access
    Réponses: 8
    Dernier message: 14/12/2005, 15h31
  3. Problème de jointure entre 3 tables
    Par Yphon dans le forum Langage SQL
    Réponses: 7
    Dernier message: 21/09/2005, 16h58
  4. Problème de jointure entre 2 ou 3 tables
    Par NicoNGRI dans le forum Langage SQL
    Réponses: 3
    Dernier message: 02/08/2005, 13h44
  5. Problème de jointure de tables
    Par AurelBUD dans le forum Langage SQL
    Réponses: 6
    Dernier message: 20/04/2005, 17h27

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