31 votes

Joindre une ligne à plusieurs lignes dans une autre table

J'ai une table à entités (appelons-les des personnes) et des propriétés (une personne peut avoir un nombre arbitraire de propriétés). Ex :

Personnes

Nom  Âge
--------
Jane  27
Joe   36
Jim   16

Propriétés

Nom   Propriété
-----------------
Jane   Intelligent
Jane   Drôle
Jane   Beau
Joe    Intelligent
Joe    Bourreau de travail
Jim    Drôle
Jim    Jeune

J'aimerais écrire une sélection efficace qui permettrait de sélectionner des personnes en fonction de leur âge et de renvoyer toutes ou certaines de leurs propriétés.

Ex : Personnes de plus de 26 ans
Nom Propriétés
Jane Intelligent, Drôle, Beau
Joe Intelligent, Bourreau de travail

Il est également acceptable de renvoyer l'une des propriétés et le nombre total de propriétés.

La requête doit être efficace : il y a des millions de lignes dans la table des personnes, des centaines de milliers de lignes dans la table des propriétés (donc la plupart des gens n'ont aucune propriété). Des centaines de lignes sont sélectionnées à la fois.

Est-ce qu'il y a un moyen de le faire ?

34voto

OMG Ponies Points 144785

Utilisation :

   SELECT x.name,
          GROUP_CONCAT(y.property SEPARATOR ', ')
     FROM PEOPLE x
LEFT JOIN PROPERTIES y ON y.name = x.name
    WHERE x.age > 26
 GROUP BY x.name

Vous voulez utiliser la fonction MySQL GROUP_CONCAT (documentation) afin de retourner une liste séparée par des virgules de la valeur de la propriété PROPERTIES.property.

J'ai utilisé une LEFT JOIN plutôt qu'un JOIN afin d'inclure les enregistrements PEOPLE qui n'ont pas de valeur dans la table PROPERTIES - si vous ne voulez qu'une liste de personnes avec des valeurs dans la table PROPERTIES, utilisez :

   SELECT x.name,
          GROUP_CONCAT(y.property SEPARATOR ', ')
     FROM PEOPLE x
     JOIN PROPERTIES y ON y.name = x.name
    WHERE x.age > 26
 GROUP BY x.name

Je sais que c'est un exemple, mais utiliser un nom est un mauvais choix pour l'intégrité référentielle lorsque l'on considère combien de "John Smith" il y a. Attribuer un user_id, étant une valeur unique par utilisateur, serait un meilleur choix.

4voto

mayur awati Points 37
SELECT x.nom,(select GROUP_CONCAT(y.Properties SEPARATOR ', ')
FROM PROPERTIES y 
WHERE y.nom.=x.nom ) as Properties FROM mst_People x 

essayer cela

3voto

Alec Points 5339

Vous pouvez utiliser INNER JOIN pour lier les deux tables ensemble. Plus d'informations sur les JOINs.

SELECT *
FROM People P
INNER JOIN Properties Pr
  ON Pr.Name = P.Name
WHERE P.Name = 'Joe' -- ou un âge spécifique, etc

Cependant, il est souvent beaucoup plus rapide d'ajouter une clé primaire unique à des tables comme celles-ci, et de créer un index pour augmenter la vitesse.

Supposons que la table People ait un champ id
Et que la table Properties ait un champ peopleId pour les relier ensemble

Alors, la requête ressemblerait à ceci:

SELECT *
FROM People P
INNER JOIN Properties Pr
  ON Pr.id = P.peopleId
WHERE P.Name = 'Joe'

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X