Vinzenz Mai: Schwieriger Query

Beitrag lesen

Hallo,

bitte hilf mir noch ein wenig mehr, ich schaff das so nicht..

gehen wir zurück zum Start. Du hast folgende zwei Tabellen:

user:
id username
1  hans
2  franz
3  ferdinand
4  klaus
5  bernd
6  Fridolin

users_friends:
userone usertwo status
1       2       1
1       5       2
1       6       1
3       4       1
2       1       1

Das gewünschte Ergebnis sieht wie folgt aus:

franz
Fridolin

Begründung:
Gib mir alle Freunde (status = 1) von Hans (d.h. entweder userone ist 1 oder usertwo ist 1). Jeder Freund soll nur ein einziges Mal im Ergebnis aufgeführt werden. Ich bin nur an den Freunden interessiert, deren Name mit "F" beginnt, dabei spielt Groß- und Kleinschreibung keine Rolle.

Mein Lösungsvorschlag war daher:

Gib mir die eindeutige Liste
    der Benutzernamen
aus
    der Tabelle user
die mit der Tabelle users_friends verknüpft ist
    über Gleichheit der Werte in den Spalten id und usertwo
wobei nur die Werte interessieren
    mit dem Wert 1 in der Spalte userone (sprich Hans)
    und dem Status 1 (d.h. Freund)
verbunden mit
der eindeutigen Liste
    der Benutzernamen
aus
    der Tabelle user
die mit der Tabelle user_friends verknüpft ist
    über Gleichheit der Werte in den Spalten id und userone(!)
wobei nur die Werte interssieren
    mit dem Wert 1 in der Spalte usertwo (sprich Hans)
    und dem Status 1 (d.h. Freund)

Schauen wir es uns Schritt für Schritt an:

1. Ermittle alle Freunde von Hans, wenn die User-ID von Hans in der Spalte
   usertwo steht:

-- Gib mir die Liste  
SELECT  
--    der Benutzernamen  
    u.username  
-- aus  
FROM  
--    der Tabelle user  
    user u                   -- die ich mit dem Aliasnamen u anspreche  
-- die mit der Tabelle users_friends verknüpft ist  
INNER JOIN  
    users_friends uf         -- mit dem Aliasnamen uf  
--    über Gleichheit der Werte in den Spalten id und userone  
ON  
    u.id = uf.userone  
-- wobei nur die Werte interessieren  
WHERE  
--    mit dem Wert 1 in der Spalte usertwo (sprich Hans)  
    uf.usertwo = 1  
--    und dem Status 1 (d.h. Freund)  
AND  
    uf.status = 1  
--     und die mit dem Buchstaben "F" beginnen  
AND  
    u.username LIKE 'F%'  

Diese Abfrage liefert das Ergebnis

username
--------
franz

(dein letzter Datensatz ist der einzige, der die Bedingungen erfüllt)

2. Schritt:
Analog ermitteln wir die Liste der Freunde von Hans, wenn die ID von Hans in
der Spalte userone steht:

SELECT  
    username  
FROM  
    user u  
INNER JOIN  
    users_friends uf  
ON  
    u.id = uf.usertwo        -- diesmal ist der Freund in Spalte usertwo  
WHERE  
    uf.userone = 1           -- nur Freunde von Hans als userone  
AND  
    uf.status = 1            -- Freunde!  
AND  
    u.username LIKE 'F%'     -- nur Freunde, deren Name mit "F" beginnt  

Diese Abfrage liefert (aus Datensatz 1 und 3)

username
--------
franz
Fridolin

3. Schritt:
Verbinde beide Ergebnismengen mit UNION. Da gleiche Datensätze nur einmal vorkommen dürfen (sprich: franz darf nur einmal vorkommen, nicht zweimal), könnten wir UNION DISTINCT verwenden - da dies das Standardverhalten von UNION ist, können wir DISTINCT einfach weglassen :-)

SELECT  
    username  
FROM  
    user u  
INNER JOIN  
    users_friends uf  
ON  
    u.id = uf.usertwo  
WHERE  
    uf.status = 1  
AND  
    uf.userone = 1  
AND  
    u.username LIKE 'F%'  
  
UNION DISTINCT                  -- DISTINCT ist hier optional  
	  
SELECT  
    username  
FROM  
    user u  
INNER JOIN  
    users_friends uf  
ON  
    u.id = uf.userone  
WHERE  
    uf.status = 1  
AND  
    uf.usertwo = 1	  
AND  
    u.username LIKE 'F%'  
AND  
    uf.usertwo = 1	

und erhalten - wie gewünscht:

username
--------
franz
Fridolin

Anmerkung: welche der beiden Abfrage als erste genommen wird, spielt keine Rolle :-)

Freundliche Grüße

Vinzenz