2015-09-03 3 views
0

J'ai deux tables dont l'une contient des informations sur les personnes et les parcelles. Chaque ligne de cette table est unique. Il n'y a pas de données répétitives. C'est quelque chose comme suit;Joindre deux tables, une avec des lignes uniques identiques et l'autre avec plusieurs lignes correspondantes

enter image description here

De plus, j'ai ce tableau qui comprend des explications sur ces lignes uniques ci-dessus. Par exemple

enter image description here

Comme vous pouvez le voir, il y a 3 explications différentes pour seulement « Jane ». Je veux ajouter des colonnes d'explication1, d'explication2, d'explication3 à la première table et mettre à jour ces champs avec l'information correspondante de la deuxième table.

Toutefois, le problème se pose exactement à ce stade. Lorsque je sélectionne les champs Name, Name, Parcel et Block des deux tables, toutes les colonnes d'explication qui doivent être mises à jour avec les explications correspondantes sont remplies juste avec la première explication. Par exemple, tous les champs d'explication1, d'explication2, d'explication3 pour "Jane Black" dans la première rangée du premier tableau sont mis à jour avec seulement "Lorem ipsum dolor sit". Les explications restantes de la deuxième table restent inutilisées. En résumé, je me demande si la façon dont j'aborde le problème n'est pas raisonnable ou existe-t-il un moyen de résoudre ce problème à la suite de mon approche? (j'utilise à la fois l'accès, mysql comme RDBMS, etc.)

+1

Pourquoi voulez-vous ajouter 3 colonnes à la première table? Que se passe-t-il quand vous obtenez une situation où il y a 4 explications, ajouterez-vous une 4ème colonne? Il me semble que le changement que vous voulez faire est une régression, pas une amélioration * (vous dénormaliserez les données, alors qu'en général vous devriez normaliser les données) *. Mon conseil est de ne pas faire ce que vous suggérez. – MatBailie

+0

Dans Oracle, j'utiliserais la fonction LISTAGG pour concaténer l'explication du même nom. Ensuite, je voudrais rejoindre ce résultat à votre table principale. Voyez si vous avez un moyen/substitut de la fonction LISTAGG dans ms-access. – Utsav

+1

'sélectionner Nom, Prénom, Parcel et Bloquer, group_concat (explication) du groupe table2 par Non, Nom, Prénom' – splash58

Répondre

0

Tout à fait une mauvaise façon de le faire et non testé.

Il utilise 3 requêtes sous qui obtiennent les explications nécessaires à la 1ère, 2ème et 3ème colonnes explication: -

SELECT t1.name, t1.parcel, t1.block, t1.share, t1.id, t2a.explanation, t2b.explanation, t2c.explanation 
FROM table1 t1 
LEFT OUTER JOIN 
(
    SELECT t21.name, t21.parcel, t21.block, t21.share, t21.id, t21.explanation 
    FROM table2 t21 
    LEFT OUTER JOIN table2 t22 
    ON t21.name = t22.name AND t21.surname = t22.surname AND t21.parcel = t22.parcel AND t21.block = t22.block AND t21.share = t22.share AND t21.id = t22.id AND t1.o > t2.no 
    GROUP BY t21.name, t21.parcel, t21.block, t21.share, t21.id, t21.explanation 
    HAVING COUNT(t22.No) = 0 
) t2a ON t1.name = t2a.name AND t2.surname = t2a.surname AND t1.parcel = t2a.parcel AND t1.block = t2a.block AND t1.share = t2a.share AND t1.id = t2a.id 
LEFT OUTER JOIN 
(
    SELECT t21.name, t21.parcel, t21.block, t21.share, t21.id, t21.explanation 
    FROM table2 t21 
    LEFT OUTER JOIN table2 t22 
    ON t21.name = t22.name AND t21.surname = t22.surname AND t21.parcel = t22.parcel AND t21.block = t22.block AND t21.share = t22.share AND t21.id = t22.id AND t1.o > t2.no 
    GROUP BY t21.name, t21.parcel, t21.block, t21.share, t21.id, t21.explanation 
    HAVING COUNT(t22.No) = 0 
) t2b ON t1.name = t2b.name AND t2.surname = t2b.surname AND t1.parcel = t2b.parcel AND t1.block = t2b.block AND t1.share = t2b.share AND t1.id = t2b.id 
LEFT OUTER JOIN 
(
    SELECT t21.name, t21.parcel, t21.block, t21.share, t21.id, t21.explanation 
    FROM table2 t21 
    LEFT OUTER JOIN table2 t22 
    ON t21.name = t22.name AND t21.surname = t22.surname AND t21.parcel = t22.parcel AND t21.block = t22.block AND t21.share = t22.share AND t21.id = t22.id AND t1.o > t2.no 
    GROUP BY t21.name, t21.parcel, t21.block, t21.share, t21.id, t21.explanation 
    HAVING COUNT(t22.No) = 0 
) t2c ON t1.name = t2c.name AND t2.surname = t2c.surname AND t1.parcel = t2c.parcel AND t1.block = t2c.block AND t1.share = t2c.share AND t1.id = t2c.id 

un peu plus simple mais moins fiable est l'utilisation GROUP_CONCAT et SUBSTRING_INDEX. Cela obtient une chaîne de toutes les explications séparées par une chaîne aléatoire (j'ai utilisé ~ # ~ ## ~ ici), puis en la décomposant en en choisissant une différente pour chaque colonne. Cela échouera bien sûr si une explication contient la chaîne que vous utilisez pour la délimiter.

SELECT t1.name, 
     t1.parcel, 
     t1.block, 
     t1.share, 
     t1.id, 
     SUBSTRING_INDEX(GROUP_CONCAT(t2.explanation ORDER BY t2.no SEPARATOR '~#~#~'), '~#~#~', 1), 
     IF(COUNT(t2.no) >= 2, SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(t2.explanation ORDER BY t2.no SEPARATOR '~#~#~'), '~#~#~', 1), '~#~#~', -1), NULL), 
     IF(COUNT(t2.no) >= 2, SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(t2.explanation ORDER BY t2.no SEPARATOR '~#~#~'), '~#~#~', 2), '~#~#~', -1), NULL) 
FROM table1 t1 
LEFT OUTER JOIN table2 t2 
ON t1.name = t2.name AND t2.surname = t2.surname AND t1.parcel = t2.parcel AND t1.block = t2.block AND t1.share = t2.share AND t1.id = t2.id 
GROUP BY t1.name, 
     t1.parcel, 
     t1.block, 
     t1.share, 
     t1.id 

Mais personnellement, je ferais probablement cela dans du code en dehors de SQL.