6 Stimmen

eine Tabelle mehrfach mit anderen Tabellen verbinden

Ich habe drei Tabellen:

Tabelle User( userid benutzername)

Tabelle Schlüssel( userid keyid)

Tabelle Laptop( Benutzerkennung laptopid)

Ich möchte alle Benutzer, die entweder einen Schlüssel oder einen Laptop oder beides haben. Wie schreibe ich die Abfrage so, dass sie eine Verknüpfung zwischen der Tabelle Benutzer und der Tabelle Schlüssel sowie eine Verknüpfung zwischen der Tabelle Benutzer und der Tabelle Laptop verwendet?

Das Hauptproblem ist, dass in dem tatsächlichen Szenario gibt es zwölf oder so Tabelle verbindet, etw. wie:

" select .. From a left join b on (...), c join d on (..),e,f,g where ...",

und ich sehe, dass a mit b verbunden werden könnte, und a könnte auch mit f verbunden werden. Also angenommen, ich kann die Tabellen a, b und f nicht nebeneinander erscheinen lassen, wie schreibe ich die SQL-Abfrage?

0 Stimmen

Jeder Benutzer muss einen Schlüssel oder einen Laptop haben. Oder?

0 Stimmen

U könnte richtig sein, könnte falsch sein, aber so total ein dont care! immer noch Spaß aber :)

0 Stimmen

Q1: Wollen Sie nur den Benutzer (userid) wissen oder auch, was genau er hatte? Q2: Kann ein Benutzer mehr als ein Element eines Typs haben (2 Laptops oder 3 Schlüssel)?

10voto

Andomar Punkte 224164

Sie können mehrere Joins verwenden, um mehrere Tabellen zu kombinieren:

select *
from user u
left join key k on u.userid = k.userid
left join laptop l on l.userid = u.userid

Eine "linke Verknüpfung" findet auch Benutzer, die weder einen Schlüssel noch einen Laptop haben. Wenn Sie beides durch "inner join" ersetzen, werden nur Benutzer mit einem Laptop und einem Schlüssel gefunden.

Wenn eine "linke Verknüpfung" keine Zeile findet, gibt sie in ihren Feldern NULL zurück. Sie können also alle Benutzer auswählen, die entweder einen Laptop oder einen Schlüssel haben, wie folgt:

select *
from user u
left join key k on u.userid = k.userid
left join laptop l on l.userid = u.userid
where k.userid is not null or l.userid is not null

NULL ist insofern etwas Besonderes, als man es wie "Feld ist nicht null" vergleicht und nicht wie "Feld <> null".

Nach Ihrem Kommentar hinzugefügt: Nehmen wir an, Sie haben eine Tabelle Maus, die sich auf Laptop bezieht, aber nicht auf Benutzer. Sie können das wie verbinden:

select *
from user u
left join laptop l on l.userid = u.userid
left join mouse m on m.laptopid = l.laptopid

Wenn dies keine Antwort auf Ihre Frage ist, müssen Sie sie weiter klären.

0 Stimmen

Ich denke, die letzte u.userid sollte k.userid sein.

0 Stimmen

Entschuldigung, dass ich die Frage nicht vorher geklärt habe: Ich habe die Frage um weitere Details ergänzt, so dass Ihre Antwort mein Problem nicht zu lösen scheint.

2voto

SO User Punkte 22342
select distinct u.userid, u.username
from User u 
    left outer join Key     /* k on u.userid = k.userid */
    left outer join Laptop  /* l on u.userid = l.userid */
where k.userid is not null or l.userid is not null

EDIT "Das Hauptproblem ist, dass es im aktuellen Szenario etwa zwölf Tabellen-Joins gibt, etwa so: " select .. From a left join b on (...), c join d on (..),e,f,g where ...", und ich sehe, dass a mit b verbunden werden könnte, und a könnte auch mit f verbunden werden. Angenommen, ich kann die Tabellen a, b und f nicht nebeneinander erscheinen lassen, wie schreibe ich dann die Sql-Abfrage?"

Sie können so viele linke äußere Verknüpfungen haben wie nötig. Verbinden Sie die Tabelle mit dem Primärschlüssel mit den übrigen Tabellen oder mit einem beliebigen anderen Feld, bei dem die Feldwerte einer Tabelle mit den Feldwerten einer anderen Tabelle übereinstimmen sollten.

z.B. wird besser erklären als Worte

select * 
from a
 left outer join b on a.pk = b.fk -- a pk should match b fk
 left outer join c on a.pk = c.fk -- a pk should match c fk
 left outer join d on c.pk = d.fk -- c pk should match d fk

und so weiter

0 Stimmen

Ich habe die Frage vervollständigt, um zu zeigen, dass meine Hauptschwierigkeit darin besteht, die drei Tabellen nicht nebeneinander erscheinen zu lassen, wobei so etwas wie vollständige Tabellen-Joins (ich meine: "from c,d" usw.) dazwischen gemischt erscheinen

1 Stimmen

Sie vermissen noch eine Where-Klausel wie "where k.userid is not null or l.userid is not null" in Ihrer ersten Antwort, um die Benutzer herauszufiltern, die nichts haben.

2voto

van Punkte 66788
-- // Assuming that a user can have at max 1 items of each type
SELECT      u.*
-- // Assuming that a user can have more then 1 items of each type, just add DISTINCT:
-- // SELECT      DISTINCT u.*
FROM        "User" u
LEFT JOIN   "Key"    u1 ON u.UserID = u1.UserID
LEFT JOIN   "Laptop" u2 ON u.UserID = u2.UserID
LEFT JOIN   "Server" u3 ON u.UserID = u3.UserID
-- // ...
WHERE       COALESCE(u1.UserID, u2.UserID, u3.UserID /*,...*/) IS NOT NULL

1voto

waxwing Punkte 18142

Wie Sie den Fall beschrieben haben, wollten Sie nur wissen, ob jemand einen Laptop oder einen Schlüssel hat. Ich würde die Abfrage mit einer Unterabfrage und nicht mit einer Verknüpfung schreiben:

select * 
from user 
where userid in (select userid from key union select userid from laptop)

Der Grund dafür ist, dass bei einem Join eine Person mit mehreren Laptops oder mehreren Schlüsseln mehrfach aufgelistet wird (außer Sie verwenden distinct ). Und auch Sie verwenden distinct haben Sie am Ende eine weniger effiziente Abfrage (zumindest bei Oracle scheint der Abfrageoptimierer nicht in der Lage zu sein, einen effizienten Plan zu erstellen).

(Bearbeitet, um den Hinweis von Rashmi Pandit zu korrigieren.)

1 Stimmen

Es handelt sich nicht um eine Querverbindung, wenn Sie die linke äußere Verbindung angeben. Left Outer Join ist schneller als Subquery.

0 Stimmen

Ich habe es schnell in einer Oracle-Datenbank ausprobiert: Sie haben recht, es verursacht keinen Cross-Join. Aber es war auch nicht schneller als die Subquery-Methode - sogar mehr als doppelt so langsam.

0 Stimmen

Ich möchte sehr wenig Änderung an der Abfrage außer dem Hinzufügen von mehr JOIN und ON-Klauseln zu tun, so für jetzt bin ich auf der Suche nach einem Weg, um es ohne Verwendung von Unterabfragen zu tun. auch ich habe mysql-Datenbank, deren Verhalten möglicherweise anders als Orakel Verhalten auf verschachtelte Abfragen sein

1voto

maxbeaudoin Punkte 6052

Lösung eins:

SELECT * FROM [User] u
INNER JOIN [Key] k
ON u.userid = k.userid

UNION

SELECT * FROM [User] u
INNER JOIN Laptop l
ON u.userid = l.userid

[...]

Lösung zwei:

SELECT * FROM [User] u
LEFT JOIN [Key] k
ON u.userid = k.userid
LEFT JOIN Laptop l
ON u.userid = l.userid
LEFT JOIN [...]
WHERE k.userid IS NOT NULL
OR l.userid IS NOT NULL
OR [...]

Nur eine Vermutung, Sie könnten auch den Ausführungsplan für diese beiden überprüfen, um zu sehen, ob die UNION ein schwerer ist oder umgekehrt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X