2012-10-10 7 views
5

Estoy tratando de encontrar los pares de los usuarios que disfrutan de la misma serie de programas de televisión en este ejemplo simplificado¿Cómo encuentro pares que comparten una propiedad (columna) a través de múltiples tuplas (filas)?

Digamos que tengo una tabla donde cada usuario tiene una entrada para cada programa de televisión que disfruten:

|USER | Show  | 
|-----|-------------| 
|001 | Lost  | 
|001 | South Park | 
|002 | Lost  | 
|003 | Lost  | 
|003 | South Park | 
|004 | South Park | 
|005 | Lost  | 
|006 | Lost  | 

entonces me gustaría resultado de:

|USER1 |USER2 | 
|------|------| 
|001 |003 | 
|003 |001 | 
|002 |005 | 
|002 |006 | 
|005 |002 | 
|005 |006 | 
|006 |002 | 
|006 |005 | 

o una versión aún mejor sería:

|USER1 |USER2 | 
|------|------| 
|001 |003 | 
|002 |005 | 
|002 |006 | 
|005 |006 | 

Lo que básicamente dice: Usuario 1 le gusta el mismo conjunto de programas como usuario 3.

He estado jugando con GROUP BY y unirse, pero todavía no puedo encontrar la respuesta :(.

Hasta ahora, he encontrado que el uso de

SELECT s1.User as USER1, s2.User as USER2, s1.Show as Show 
FROM Shows s1 JOIN (SELECT * FROM Shows) s2 
ON s1.Shows=s2.Shows AND s1.User!=s2.User; 

que produce pares de usuarios y el espectáculo que tienen en común. Pero no sé a dónde ir desde aquí.

+1

Muéstranos con lo que has estado jugando. – Kermit

+0

Creo que el resultado esperado no coincide con los datos de muestra proporcionados. En los datos de muestra tiene 6 usuarios pero solo dos programas de TV y en el resultado esperado es viceversa. –

+0

SELECT s1.User como Usuario1, Usuario2 s2.User, s1.Show Como demostración provenientes de los shows s1 UNEN (SELECT * \t provenientes de los shows) s2 EN s1.Shows = s2.Shows Y s1.User! = S2 .Usuario; Esto produce una lista de pares que le gusta al menos un mismo programa de TV. @DanielHilgarth Quiero encontrar pares de usuarios que miran TODOS los mismos programas de TV.El usuario 1 y el usuario 3 ven Lost y South Park. El usuario 2 y el usuario 5 ambos ven Lost. El usuario 2 y el usuario 6 ambos ven Lost. etc. –

Respuesta

4

Si usted puede aceptar CSV en lugar de resultados tabulados, simplemente podría grupo de la mesa dos veces:

SELECT GROUP_CONCAT(User) FROM (
    SELECT User, GROUP_CONCAT(DISTINCT `Show` ORDER BY `Show` SEPARATOR 0x1e) AS s 
    FROM  Shows 
    GROUP BY User 
) t GROUP BY s 

De lo contrario, puede unirse a la sub consulta anterior a sí mismo:

SELECT DISTINCT LEAST(t.User, u.User) AS User1, 
      GREATEST(t.User, u.User) AS User2 
FROM (
    SELECT User, GROUP_CONCAT(DISTINCT `Show` ORDER BY `Show` SEPARATOR 0x1e) AS s 
    FROM  Shows 
    GROUP BY User 
) t JOIN (
    SELECT User, GROUP_CONCAT(DISTINCT `Show` ORDER BY `Show` SEPARATOR 0x1e) AS s 
    FROM  Shows 
    GROUP BY User 
) u USING (s) 
WHERE t.User <> u.User 

verlos en sqlfiddle.

Por supuesto, si duplicados (User, Show) pares están garantizados de no existir en la tabla Shows, se podría mejorar el rendimiento mediante la eliminación de la palabra clave de los DISTINCTGROUP_CONCAT() agregaciones.

+0

¡Acabo de probar esto y funcionó de maravilla! ¡Gracias! No sabía que cosas como GROUP_CONCAT existieran. –

+0

@HeartAce, he agregado otra respuesta para su diversión. – Jodrell

0

Después de pensar en esto más me preguntaba, ¿y si Agrupé los grupos,

select 
    group_concat( 
     User 
     order by User 
     separator ', ' 
    ) LikeViewers 
    , Shows 
from 
(
select 
     User 
    , group_concat(
     concat('"', Show, '"') 
     order by Show 
     separator ', ' 
     ) Shows 
    from 
    Viewings 
    group by 
    User 
) ViewerGroups 
group by 
    Shows 

que produce una salida como esta

|LikeViewers |Shows    | 
|-------------|--------------------| 
|002, 005, 006|"Lost"    | 
|001, 003  |"Lost", "South Park"| 
|004   |"South Park"  | 

cierto, los resultados podrían ser más reutilizable pero pensé fue una idea interesante

Fiddle Here

Cuestiones relacionadas