LEFT JOIN in una relazione N a N

di il
5 risposte

LEFT JOIN in una relazione N a N

Buonasera a tutti, ho bisogno di alcuni chiarimenti riguardante una query che non riesco a progettare.
Allora, il seguente database è progettato in questo modo:
Utenti: (ID, Nome)
Film: (Cod, Titolo)
Votare: (ID,Cod,Voto)

Gli utenti possono votare più film, mentre più film possono essere votati da più utenti.
In linea generare si tratta di una relazione N a N tra Utenti e Film che risolvo con la tabella Votare dove:
Utenti.ID è uguale a Votare.ID e Film.Cod è uguale a Votare.Cod .

La query che devo progettare deve restituirmi: Dato il titolo di un film i voti di tutti gli utenti (inclusi quelli che non hanno votato quel film)
Il punto che ho evidenziato in grassetto è esattamente quello che non riesco a produrre.

Una possibile soluzione che stavo pensado era questa:
SELECT * FROM utenti LEFT OUTER JOIN votare ON utenti.ID = votare.ID
LEFT OUTER JOIN film ON votare.Cod = film.Cod
WHERE Titolo = 'FilmACaso'
ma ovviamente non mi restituisce il risultato desiderato, inoltre non riesco a capire perché dato che il LEFT OUTER JOIN dovrebbe includere anche gli utenti che non hanno il voto.

5 Risposte

  • Re: LEFT JOIN in una relazione N a N

    Salve,
    il filtro di WHERE scarta tutte le righe del prodotto che non soddisfino Titolo = 'xx'
    quindi io prima otterrei il risultato "netto" della proiezione soddisfatta dal filtro, e quindi aggiungerei le righe "nulle" degli utenti che non abbiano votato...
    trivialmente, data la popolazione
    INSERT INTO Utenti
    	VALUES ( 1, 'UA' ), ( 2, 'UB' ), ( 3, 'UC' ), ( 4, 'UD' ), ( 5, 'UE' ), ( 6, 'UG' );
    INSERT INTO Film
    	VALUES ( 1, 'FA' ), ( 2, 'FB' ), ( 3, 'FC' ), ( 4, 'FD' ), ( 5, 'FE' ), ( 6, 'FG' );
    INSERT INTO Votare
    	VALUES ( 1, 1, 10 ), 
    		( 2, 1, 9), ( 2, 2, 8), 
    		( 3, 1, 8), ( 3, 2, 8), ( 3, 3, 7), 
    		( 4, 1, 10), ( 4, 2, 9), ( 4, 3, 8), ( 4, 4, 7), 
    		( 5, 1, 10), ( 5, 2, 9), ( 5, 3, 8), ( 5, 4, 7), ( 5, 5, 6);
    
    prima otterrei il prodotto delle votazioni valide, al quale poi aggiungere i non votanti:
    
    DECLARE @film varchar(5) = 'FD';
    
    WITH cte AS (
    	SELECT v.*
    		FROM Film f
    			JOIN Votare v ON v.Cod = f.Cod
    		WHERE f.Titolo = @film
    	)
    	SELECT *
    		FROM Utenti u
    			LEFT JOIN cte ON cte.Id = u.Id;
    --<-------------
    Id          Nome  Id          Cod         Voto
    ----------- ----- ----------- ----------- -----------
    1           UA    NULL        NULL        NULL
    2           UB    NULL        NULL        NULL
    3           UC    NULL        NULL        NULL
    4           UD    4           4           7
    5           UE    5           4           7
    6           UG    NULL        NULL        NULL
    
    salutoni romagnoli
    --
    Andrea
  • Re: LEFT JOIN in una relazione N a N

    Ciao, scusami se ti rispondo ora, grazie per la risposta
    La soluzione funziona divinamente, però vorrei sapere nel dettaglio cosa faccia il "WITH cte", è la prima volta che vedo questa keyword
  • Re: LEFT JOIN in una relazione N a N

    Salve,

    sono uno standard ANSI per definire un resultset temporaneo utilizzabile "al pari" di una subquery... vedi ad esempio https://www.geeksforgeeks.org/cte-in-sql

    poi ogni dbms riesce ad integrarlo come meglio puo/vuole/riesce

    nel mio caso, ho utilizzato la sintassi T-SQL di Mircrosoft SQL Server, che comunque resta aderente allo standard in questa esemplificazione...

    salutoni romagnoli
    --
    Andrea
  • Re: LEFT JOIN in una relazione N a N

    Left join (tutti gli utenti + film che hanno preso incluso nessuno)
    Right join l'opposto di left join

    Inner join (solo gli utenti che hanno visto i filmi e l'elenco dei film visti)
    Outer join (tutti gli utenti e tutti i film cioè l'opposto di inner)
    Togli outer...
  • Re: LEFT JOIN in una relazione N a N

    Salve @sihsandrea,

    cosa intendi?

    LEFT JOIN e LEFT OUTER JOIN sono esattamente la stessa cosa


    salutoni romagnoli
    --
    Andrea
Devi accedere o registrarti per scrivere nel forum
5 risposte