2012-10-10 6 views
5

Sto cercando di trovare le coppie di utenti che godono lo stesso insieme di spettacoli televisivi in ​​questo esempio semplificatoCome trovo le coppie che condividono la proprietà (colonna) attraverso più tuple (righe)?

Diciamo che ho una tabella in cui ogni utente riceve una voce per ogni TV Show che essi godono:

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

Poi vorrei un risultato di:

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

o una versione ancora migliore sarebbe:

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

che dice sostanzialmente: 1 utente piace lo stesso insieme di spettacoli come utente 3.

Ho giocato in giro con GROUP BY e JOIN, ma non riesco ancora a trovare la risposta :(.

Finora, ho trovato che l'uso di

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; 

che produce coppie di utenti e lo spettacolo che hanno in comune. Ma non so da dove andare.

+1

ci mostrano quello che hai giocato in giro con. – Kermit

+0

Penso che il risultato atteso non corrisponda ai dati campione forniti. Nei dati di esempio si hanno 6 utenti ma solo due programmi TV e nel risultato atteso è vice versa. –

+0

SELEZIONA s1.User come USER1, s2.User come UTENTE2, s1.Show come Visualizza suoi spettacoli dal s1 ISCRIVITI (SELECT * FROM \t Spettacoli) s2 ON s1.Shows = s2.Shows E s1.User! = S2 .Utente; Questo produce un elenco di coppie a cui piace almeno uno stesso programma TV. @DanielHilgarth Voglio trovare coppie di utenti che guardano TUTTI gli stessi programmi TV.Utente 1 e Utente 3 guardano entrambi Lost e South Park. Utente 2 e Utente 5 entrambi guardano Lost. Utente 2 e Utente 6 entrambi guardano Lost. ecc. –

risposta

4

Se si può accettare CSV invece di risultati tabulati, si potrebbe semplicemente gruppo tabella due volte:

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 

caso contrario, è possibile aderire al subquery sopra a se stesso:

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 

vederli su sqlfiddle.

Naturalmente, se duplicati (User, Show) coppie sono garantiti non esistere nella tabella Shows, si potrebbe migliorare le prestazioni eliminando la parola DISTINCT dalle GROUP_CONCAT() aggregazioni.

+0

Ho appena provato questo e ha funzionato benissimo! Grazie! Non sapevo che cose come GROUP_CONCAT esistessero. –

+0

@HeartAce, ho aggiunto un'altra risposta per il tuo divertimento. – Jodrell

0

Dopo riflessione al più mi sono chiesto, se ho raggruppato i gruppi,

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 

che produce un output come questo

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

certamente, i risultati potrebbero essere più riutilizzabile ma ho pensato è stata un'idea interessante

Fiddle Here

Problemi correlati