2016-04-21 3 views
0

Ich habe 3 Tabellen in MySQL und ich muss alle Instanzen finden, wo ein Benutzer kein bestimmtes Widget hat.MySQL Join 3 Tabellen und finde "fehlende" Zeilen in einer Tabelle

Beispiel:

Users 
tenant_id user_id user_name 
1   1  Bob 
1   2  Fred 
1   3  John 
1   4  Tom 

Widgets 
tenant_id widget_id widget_name 
1   1   Red 
1   2   Blue 
1   3   Green 
1   4   Black 

Usage 
tenant_id user_id widget_id 
1   1  1 
1   1  2 
1   1  4 
1   2  2 
1   2  3 
1   2  4 
1   3  1 
1   3  2 
1   3  3 
1   3  4 
1   4  1 
1   4  2 
1   4  3 

Missing in table three are: 
user_name widget_name 
Bob  Green 
Fred  Red 
Tom  Black 

Die Abfrage ich zu verwenden Ich versuche ist:

SELECT 
    user_name, widget_name 
FROM 
    users left join widgets on users.tenant_id=widgets.tenant_id 
WHERE 
    NOT EXISTS (
    SELECT 1 FROM usage WHERE user_id = users.user_id AND widget_id = widgets.widget_id 
) and users.tenant_id=1 

Wenn die Abfrage abgeschlossen ist es eine riesige Liste von Benutzernamen und Widget-Namen zurück bringt aber viele hundert mehr, als ich erwarten von.

Ich bin mir nicht sicher, ob der Join falsch ist oder ob ich eine Gruppierung des Ergebnisses vornehmen muss.

+0

Welches Ergebnis bekommen Sie? Bitte fügen Sie das in Ihre Antwort ein oder richten Sie eine SQL Fiddle ein. –

Antwort

1

Hier ist die Idee hinter dieser Art von Abfrage. Erzeuge zuerst alle möglichen Kombinationen von Benutzern und Widgets. Dann filtern diejenigen heraus, die es gibt:

select u.user_name, w.widget_name 
from users u join 
    widgets w 
    on u.tenant_id = w.tenant_id 
where not exists (select 1 
        from usage us 
        where us.user_id = u.user_id and us.widget_id = w.widget_id and 
         us.tenant_id = u.tenant_id 
       ) and 
     u.tenant_id = 1; 

Ich denke, Ihre Logik die tenant_id in der usage Tabelle fehlt. Ich bin mir jedoch nicht sicher, ob das einen großen Unterschied macht.

+0

Ich habe dies verwendet und es gibt das richtige Ergebnis - die andere Sache, die ich bemerke, ist, dass Sie Join verwenden, aber ich war links Join, könnte das einen Unterschied machen? – bhttoan

+1

@ bhttoan. . . Wenn Sie Benutzer ohne Widgets haben, würde das den Unterschied erklären. –

0

Sie können ein kartesisches Produkt und einige innere verwenden beitreten

select b.user_name, c.widget_name 
from 
(select u.user_id, w.widget_id 
from Users as u, Widgets as w 
where (u.user_id, w.widget_id) not in (select user_id, widget_id 
              from Usage)) as a 
inner join Users as b on a.user_id = b.user_id 
inner join Widgets as c on a.widget_id = c.widget_id; 
0

die unter einem Versuchen, für mich gearbeitet.

select w.widget_name, u.user_name 
from widgets w join users u on w.tenant_id = u.tenant_id 
where (w.widget_name, u.user_name) not in 
      (select w.widget_name, u.user_name 
       from widgets w join `usage` us on us.widget_id = w.widget_id 
       join users u on u.user_id = us.user_id);