2012-03-07 12 views
5

Ho le tabelle users, locations e una tabella di join. La tabella di join ha anche un valore di classificazione per ogni individuo in quella posizione, perché questi individui hanno ranghi più alti in determinate località rispetto ad altre posizioni.Che tipo di Join per vedere i valori inesistenti nella tabella Join?

users 
========= 
id | name 
========= 
1 | john 
2 | bob 
3 | alex 

locations 
=============== 
id | name 
=============== 
1 | san diego 
2 | dallas 
3 | new york 
4 | denver 

join_users_locations 
============================== 
user_id | location_id | rank 
============================== 
     2 |   1 | 4 
     2 |   2 | 3 
     2 |   4 | 2 
     3 |   1 | 2 
     3 |   2 | 4 

Si può vedere che nella tabella di join un utente viene elencato solo se ha una classifica in quella posizione. Non sono nemmeno nella tabella se il loro rango è zero/nullo.

Sono voler ottenere i risultati delle query come questo:

name | location | rank 
======================= 
bob | san diego | 4 
bob | dallas | 3 
bob | new york | 0 
bob | denver | 2 

Come potete vedere, voglio tutte le sedi di essere nella lista, anche quelli che l'utente non si unisce con (solo dare quei campi un valore di rango pari a zero).

E 'facile per ottenere l'elenco delle posizioni e si classifica per le posizioni che lui/lei si unisce con:

SELECT 
    u.name, 
FROM users u 
LEFT JOIN join_users_locations jul ON jul.user_id = u.id 
LEFT JOIN locations l ON l.id = jul.location_id 
WHERE u.id = 2 

Ma che elenca solo ciò che posizioni che l'utente si unisce con. Voglio vedere anche le posizioni non associate.

So che questo è possibile, ma non sono sicuro di quale sia la soluzione. Ho provato diversi tipi di JOIN con vari risultati.

SQL FIDDLE HERE

+0

Hai provato a sinistra outer join? – Ciprian

risposta

3

Si può fare questo con un CROSS JOINusers-locations.

SELECT 
    u.name, 
    l.name AS location, 
    IFNULL(jul.rank, 0) AS rank 
FROM 
    users u CROSS JOIN 
    locations l LEFT JOIN 
    join_users_locations jul 
     ON jul.user_id = u.ID 
     AND jul.location_id = l.id 
WHERE u.id = 2 
+1

Ah interessante ... mai usato un CROSS JOIN prima. Ho funzionato perfettamente qui: http://sqlfiddle.com/#!2/4a46a/8 Grazie –

0

Sinistra esterno join. I join esterni includono tutto "a sinistra" del join, anche se non esiste una tupla corrispondente a sinistra. Probabilmente otterrai nullo invece di 0. È ok? (è possibile impostare la visualizzazione valore nullo per essere 0, in caso contrario)

+1

Ti piace questo? http://sqlfiddle.com/#!2/4a46a/4 Non riesco a farlo funzionare. –

+1

, tuttavia, tutti i valori inseriti hanno gradi. Se cambio uno degli inserti per avere un rank di null e lo rieseguo ottengo esattamente quello che vuoi. Tranne uno spazio invece di uno 0. http://sqlfiddle.com/#!2/9f52c/2 – Colleen

+0

Non sto seguendo. Puoi copiare/incollare un URL di Fiddle SQL? –

0
SELECT u.name,l.name as location,jul.rank 
FROM users u,locations l,join_users_locations jul 
WHERE u.id = jul.user_id AND 
     jul.location_id = l.id AND 
     u.id = 2 
UNION 
SELECT 'bob' AS NAME,A.NAME AS location,A.RANK_NULL AS RANK 
FROM 
(SELECT *,IFNULL(RANK,0) AS RANK_NULL 
FROM (SELECT * FROM JOIN_USERS_LOCATIONS JUL WHERE JUL.USER_ID=2)JUL 
RIGHT JOIN LOCATIONS L 
    ON JUL.LOCATION_ID = L.ID 
WHERE RANK IS NULL)A 

O

SELECT IFNULL(JUL.NAME,'bob'),L.NAME,IFNULL(RANK,0) AS RANK 
FROM (SELECT U.NAME,JUL.USER_ID,JUL.LOCATION_ID,JUL.RANK 
     FROM USERS U,JOIN_USERS_LOCATIONS JUL 
     WHERE U.ID=JUL.USER_ID AND JUL.USER_ID=2 
    ) JUL 
     RIGHT JOIN 
     LOCATIONS L 
    ON JUL.LOCATION_ID = L.ID 
+0

Gli impliciti join nella clausola where avrebbero lo stesso effetto di fare inner join ... jul.rank non sarebbe mai nullo, e questo non può restituire nessun luogo per il quale l'utente non ha un record in 'join_user_locations' ... –

+0

Lo ha reso molto complicato per voi ragazzi ... :) – Teja