2016-07-07 2 views
0

Diese Abfrage ist keine rechtliche Syntax und ich versuche zu verstehen, was die effiziente Art des Schreibens ist. Dies ist, was ich habe:Richtiger Weg, um eine MySQL-Abfrage zu schreiben, die eine abgeleitete Spalte und mehrere Joins verwendet

SELECT a.*, b.id, lapsed FROM 
    (SELECT DATEDIFF(CURDATE(), MAX(day)) AS lapsed FROM c) AS x 
    FROM first_table a 
    INNER JOIN second_table b ON a.id = b.some_id 
    INNER JOIN third_table c ON c.user_id = a.user_id 
    WHERE a.some_col = 'm' 
    AND b.num >= lapsed 

Es gibt drei Tabellen verbunden werden. Normalerweise wäre das trivial, aber das Problem ist mein letzter Teil der WHERE Klausel, speziell b.num >= lapsed macht einen Vergleich über einen derived Wert. Gibt es einen richtigen Weg dies zu schreiben?

+0

2 FROM ist nicht erlaubt. Aber ein LINKER JOIN bei einer Unterabfrage ist möglich. Da es sich um eine Zeile in x handelt, kann das ON-Kriterium für Join (1 = 1) sein. – LukStorms

+0

jede Chance, dass Sie eine Anfrage als Antwort einreichen können, damit ich es entsprechend markieren kann? – randombits

+0

Sie und ich haben unterschiedliche Vorstellungen darüber, wo das Problem in Ihrer Abfrage liegt. – Strawberry

Antwort

0

Angesichts der MAX() Aggregat, es sieht aus wie Sie die neueste day Wert für jeden user_id Wert von third_table wollen.

das zu bekommen, haben wir eine Abfrage wie folgt schreiben:

SELECT c.user_id 
     , DATEDIFF(CURDATE(),MAX(c.day)) AS lapsed 
    FROM third_table c 
    GROUP BY c.user_id 

Sie die Ergebnismenge dieser Abfrage als rowsource in einer anderen Abfrage verwenden können, um diese Abfrage als Inline-Ansicht anstelle einer Verwendung Tabellenreferenz. (MySQL bezeichnet eine Inline-Ansicht als "abgeleitete Tabelle".)

Wir wickeln diese Abfrage einfach in Parens und verwenden sie anstelle der Stelle, an der wir normalerweise eine Tabellenreferenz finden würden. Der Inline-Ansicht (abgeleitete Tabelle) muss ein Alias ​​zugewiesen werden.

Zum Beispiel:

SELECT a.* 
     , b.id 
     , d.lapsed 
    FROM first_table a 
    JOIN second_table b 
    ON b.some_id = a.id 
    JOIN (SELECT c.user_id 
       , DATEDIFF(CURDATE(),MAX(c.day)) AS lapsed 
      FROM third_table c 
      GROUP BY c.user_id 
     ) d 
    ON d.user_id = a.user_id 
    WHERE a.some_col = 'm' 
    AND b.num > d.lapsed 

Eine Abfrage ähnlich der ausgeführt werden soll. Aber ob das die Ergebnismenge zurückgibt, die Sie erwarten, hängt davon ab, welches Ergebnis Sie zurückgeben wollen. Ohne Angabe einer Spezifikation (abgesehen von einer ungültigen Abfragesyntax) erraten wir nur.

1

Haben Sie dies nicht getestet, aber wenn die Unterabfrage korrekt ist, sollte dies funktionieren.

Ich nahm auch an, dass das 'c' im Beispiel der Frage sich auch auf diese dritte_Tabelle bezieht und nicht auf irgendeine Tabelle/Sicht, die c genannt wird.

Und der INNER JOIN zu third_table wurde auskommentiert, da es meistens nutzlos für INNER JOIN table/views ist, wenn Sie keine Felder davon verwenden. Nun, es könnte verwendet werden, um Datensätze in dieser Tabelle zu begrenzen, aber meistens ist es einfach nutzlos.

SELECT a.*, b.id, x.lapsed 
FROM first_table a 
INNER JOIN second_table b ON a.id = b.some_id 
--INNER JOIN third_table c ON c.user_id = a.user_id 
LEFT JOIN ( 
    SELECT DATEDIFF(CURDATE(), MAX(day)) AS lapsed 
    FROM third_table 
) AS x ON (1=1) 
WHERE a.some_col = 'm' 
AND b.num >= x.lapsed; 
Verwandte Themen