2012-04-08 9 views
2

Ich habe eine riesige MySQL-Abfrage, die von JOINs abhängt.Wie mache ich meine MySQL-Abfrage mit Joins prägnanter?

SELECT m.id, l.name as location, CONCAT(u.firstName, " ", u.lastName) AS matchee, u.email AS mEmail, u.description AS description, m.time AS meetingTime 
FROM matches AS m 
LEFT JOIN locations AS l ON locationID=l.id 
LEFT JOIN users AS u ON (u.id=m.user1ID) 
WHERE m.user2ID=2 

UNION 

SELECT m.id, l.name as location, CONCAT(u.firstName, " ", u.lastName) AS matchee, u.email AS mEmail, u.description AS description, m.time AS meetingTime 
FROM matches AS m 
LEFT JOIN locations AS l ON locationID=l.id 
LEFT JOIN users AS u ON (u.id=m.user2ID) 
WHERE m.user1ID=2 

Die ersten 3 Zeilen jeder Unteranweisung geteilt durch UNION sind identisch. Wie kann ich mich an das DRY-Prinzip halten, diese drei Zeilen nicht wiederholen und diese Abfrage prägnanter gestalten?

+0

* re: * 'LINKE JOIN Benutzer AS u ON (u.id = m.user1ID) WHERE m.user2ID = 2' - Ist die tatsächliche sql wirklich Benutzer1ID gegen Benutzer2ID zu vergleichen, oder ist das nur ein Tippfehler? – Leigh

Antwort

1

Versuch auf diese Weise sollte arbeiten:

SELECT m.id, l.name as location, CONCAT(u.firstName, " ", u.lastName) AS matchee, u.email AS mEmail, u.description AS description, m.time AS meetingTime 
FROM matches AS m 
LEFT JOIN locations AS l ON locationID=l.id 
LEFT JOIN users AS u 
ON ((u.id=m.user1ID AND m.user2ID=2) OR (u.id=m.user2ID AND m.user1ID=2)) 
WHERE (m.user1ID=2 OR m.user2ID=2) 
+3

Ich glaube nicht, dass es das gleiche Ergebnis geben wird. Ich denke du brauchst auch eine WHERE-Klausel, sonst bekommst du zu viele Zeilen. –

+0

Ich stimme Mark Byers zu. Es kann mehr als erwartet zurückkehren. –

+0

Haben Sie die Abfrage versucht? – aleroot

-1

1) Ich sehe, dass Sie Benutzer passen und Sie einige Informationen zu diesem Spiel im Zusammenhang halten.

Das ist ein wenig kompliziert zu entwerfen. Der einfache Ansatz besteht lediglich darin, die Daten in Übereinstimmungen überflüssig zu machen. Auf diese Weise erhalten Sie immer die Übereinstimmung von user1ID = 2. Bedeutet, dass Sie jede Übereinstimmung für 2 mal speichern müssen, in einer user1ID und user2ID und in der zweiten mit den entgegengesetzten Werten von user1ID und user2ID. Wie gesagt, das ist überflüssig und wenn Sie viele Datensätze erwarten, empfehle ich es nicht.

2) Ein anderer Ansatz ist die Normalisierung Ihres Designs. Erstellen Sie eine andere Tabelle matchUser (MatchID, userId) (Primärschlüssel beide attrs)

SELECT ... FROM matches AS m 
LEFT JOIN locations AS l ON locationID=l.id 
LEFT JOIN users AS u ON (u.id=mu2.userId) 
INNER JOIN matchUser mu1 ON mu1.userId=2 
INNER JOIN matchUser mu2 ON mu2.matchId=mu1.matchId AND mu2.userId != 2 

So etwas wie diese, die Abfrage vielleicht falsch, ich habe es nicht getestet, aber Sie bekommen die Idee.

0
SELECT 
    s.id, 
    s.location, 
    CONCAT(u.firstName, " ", u.lastName) AS matchee, 
    u.email AS mEmail, 
    u.description AS description, 
    s.meetingTime 
FROM (
    SELECT 
    m.id, 
    l.name AS location, 
    m.time AS meetingTime, 
    CASE m.user1ID when @userID THEN m.user2ID ELSE m.user1ID END AS userID 
    FROM matches AS m 
    LEFT JOIN locations AS l ON m.locationID = l.id 
    WHERE m.user1ID = @userID OR m.user2ID = @userID 
) AS s 
LEFT JOIN users AS u ON s.userID = u.id 

Die Unterabfrage filtert die matches Tabelle auf der Benutzer-ID angegeben ist, schließt er sich an locations, zieht die erforderlichen Spalten aus den beiden Tabellen und bereitet eine einzelne userID Säule (unter Verwendung von entweder user1ID oder user2ID, je nachdem, welche der zwei ist nicht die angegebene ID) zum Beitritt mit users. Die äußere Abfrage verknüpft die Ergebnismenge des inneren SELECT mit users und zieht die restlichen Spalten, die als Ergebnis des Joins erhalten wurden.

Verwandte Themen