web-dev-qa-db-fra.com

Joindre une ligne à plusieurs lignes dans une autre table

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

Gens

Name  Age
--------
Jane  27
Joe   36
Jim   16

Propriétés

Name   Property
-----------------
Jane   Smart
Jane   Funny
Jane   Good-looking
Joe    Smart
Joe    Workaholic
Jim    Funny
Jim    Young

Je voudrais écrire une sélection efficace qui sélectionnerait des personnes en fonction de leur âge et retournerait tout ou partie de leurs propriétés.

Ex: People older than 26
Name Properties
Jane Smart, Funny, Good-looking
Joe Smart, Workaholic

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 pas de propriétés). Il y a des centaines de lignes sélectionnées à la fois.

Y a-t-il un moyen de le faire?

23
Ghostrider

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 la fonction MySQL GROUP_CONCAT ( documentation ) afin de renvoyer une liste séparée par des virgules de la valeur PROPERTIES.property.

J'ai utilisé un 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 me rends compte que c'est un exemple, mais l'utilisation d'un nom est un mauvais choix pour l'intégrité référentielle quand on considère le nombre de "John Smith". Assigner un user_id, étant une valeur numérique, serait un meilleur choix.

25
OMG Ponies
SELECT x.name,(select GROUP_CONCAT(y.Properties SEPARATOR ', ')
FROM PROPERTIES y 
WHERE y.name.=x.name ) as Properties FROM mst_People x 

essaye ça

4
mayur awati

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

SELECT *
FROM People P
INNER JOIN Properties Pr
  ON Pr.Name = P.Name
WHERE P.Name = 'Joe' -- or a specific age, etc

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

Disons que la table People a un champ id
Et la table Properties a un champ peopleId pour les lier ensemble

La requête ressemblerait alors à quelque chose comme ceci:

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