2012-06-08 13 views
9

Tengo tres tablas:JOIN y GROUP_CONCAT con tres mesas

users:  sports:   user_sports: 

id | name  id | name   id_user | id_sport | pref 
---+-------- ---+------------ --------+----------+------ 
1 | Peter  1 | Tennis    1 |  1 | 0 
2 | Alice  2 | Football   1 |  2 | 1 
3 | Bob  3 | Basketball   2 |  3 | 0 
             3 |  1 | 2 
             3 |  3 | 1 
             3 |  2 | 0 

La mesa user_sports enlaces users y sports con un orden de preferencia (pref).

Necesito hacer una consulta que devuelve esto:

id | name | sport_ids | sport_names 
---+-------+-----------+---------------------------- 
1 | Peter | 1,2  | Tennis,Football 
2 | Alice | 3   | Basketball 
3 | Bob | 2,3,1  | Football,Basketball,Tennis 

He tratado con JOIN y GROUP_CONCAT pero me da resultados extraños.
¿Debo hacer una consulta anidada?
¿Alguna idea?

+2

¿podría publicar su rutina group_concat que no funcionó? Parece ser exactamente lo que necesita (consulte esta página: http://stackoverflow.com/questions/276927/can-i-concatenate-multiple-mysql-rows-into-one-field), por lo que podría ser útil ver la consulta o determinar cómo salió mal. – user158017

Respuesta

24

No es particularmente difícil.

  1. Únase a las tres tablas utilizando la cláusula JOIN.
  2. Uso GROUP_CONCAT en los campos que le interesan.
  3. No se olvide de la cláusula GROUP BY en los campos que no está concatenación o weird things will happen


SELECT u.id, 
     u.Name, 
     Group_concat(us.id_sport order by pref) sport_ids, 
     Group_concat(s.name order by pref)  sport_names 
FROM users u 
     LEFT JOIN User_Sports us 
       ON u.id = us.id_user 
     LEFT JOIN sports s 
       ON US.id_sport = s.id 
GROUP BY u.id, 
      u.Name 

DEMO

Actualización LEFT JOIN para cuando el usuario no tenga ent en los User_Sports según los comentarios

+0

¡Increíble! +1 para sqlfiddle – Peter

+1

¿Por qué una combinación interna en lugar de una combinación izquierda? y un solo 'grupo por' parece ser suficiente: http://sqlfiddle.com/#!2/4d402/9 – Peter

+0

Las uniones internas suelen tener un mejor rendimiento que las uniones izquierdas, así que empiezo allí. ¿Le interesan los usuarios que no existen en sports_users? –

3

creo que esto es sólo un simple unirse y agregación:

select u.id, u.name, group_concat(s.name order by pref separator ',') 
from user_sports us join 
    users u 
    on us.id_user = u.id join 
    sports s 
    on us.id_sport = s.id 
group by u.id, u.name