2016-08-08 29 views
3

Ich habe zwei Tabellen mit einer Eins-zu-viele-Beziehung.Erhalte Daten mit MAX (Datum) <X

Table1 
ID name email 
Table2 
ID table1_ID date 

Ich brauche die Daten alle aus Tabelle 1 erhalten where:

MAX(date) from Table2 < "2016-01-01" 

Das funktioniert nicht. Max wird in where-Klausel als "ungültig" betrachtet. Was ich tat war:

SELECT Table1.name, Table1.email, tmp.maxdate 
FROM Table1 
JOIN ( SELECT MAX(date) maxdate, table1_ID 
     FROM Table2 
     GROUP BY table1_ID) as tmp 
    ON tmp.table1_ID = table1.id 
WHERE tmp.maxdate < "2016-01-01" 
AND  (other conditions) 

So funktioniert das. ABER ich denke, die Leistung wird schrecklich sein - explain zeigt, dass alle Table2 gelesen wird, und diese Tabelle wird viel wachsen.

Irgendeine Idee, wie ich es sonst tun könnte, oder wie ich meine aktuellen Abfrageleistungen verbessern könnte?

+0

Warum denken Sie, dass die Leistung schrecklich ist? –

+1

Es ist ein wenig merkwürdig, dass Sie tmp mit table1 verknüpfen, anstatt den Zwischenschritt für die Verknüpfung von tmp mit Tabelle 2 einzuschließen. Außerdem würde ich die WHERE-Klausel in die Unterabfrage einfügen. Abgesehen davon, sollte diese Abfrage extrem schnell indiziert sein. – Strawberry

+1

Da 'MAX (Datum)' eine Aggregation ist, kann es nicht in 'WHERE' eingefügt werden, sondern gehört stattdessen zu' HAVING'. Wie auch andere darauf hingewiesen haben, können Sie anstelle von 'HAVING MAX (date)> '2016-01-01'' einfach' WHERE date>' 2016-01-01'' verwenden. –

Antwort

2

Versuchen:

SELECT Table1.name, Table1.email, tmp.maxdate 
FROM Table1 
INNER JOIN ( SELECT MAX(date) maxdate, table1_ID 
     FROM Table2 
     GROUP BY table1_ID 
     HAVING maxdate > "2016-01-01") as tmp 
    ON tmp.table1_ID = table1.id 
WHERE 
AND  (other conditions) 

Bevor Sie nur jeder von Table2 bringen zurück und kommen mit Table1. Das wird alle ohne das maxdate> "2016-01-01" abklopfen und mit Table1 mitmachen.

+0

Das ist ein sehr guter Punkt, @Strawberry wies darauf in den Kommentaren auch, danke! –

1

Zunächst einmal glaube nicht, Test es von Ihnen selbst und überprüfen Sie es.

Zweitens, können Sie versuchen EXISTS() verwendet, die etwas schneller sein könnte weil Sie Table2 filtern und keine GROUP BY-Klausel verwenden:

SELECT * FROM Table1 t1 
WHERE EXISTS(SELECT 1 FROM Table2 t2 
      WHERE t2.date > "2016-01-01" 
       AND t1.id = t2.table1_id 
       AND <Other Conditions>) 

Sie können auch table2.date > "2016-01-01" in Ihrem Sub-Abfrage hinzuzufügen.

Zusätzlich zu berücksichtigen, indem die folgenden Indizes:

Table1(id,name,email) 
Table2(table1_id,date) 

Bitte beachte, dass ich diese Indizes auf der Grundlage der Abfrage empfehlen Ihnen zur Verfügung gestellten, wenn es zusätzliche Bedingungen diese Indizes möglicherweise nicht vollständig.

+0

Hallo und vielen Dank für Ihre Antwort! Natürlich sind die Indizes richtig eingestellt. Du hast einen sehr interessanten Punkt, immer noch mit dem Wo vorhanden. Ich denke nicht, dass es wirklich zu den anderen obligatorischen Punkten passt (Reihenfolge nach maxdate, Limit-Ergebnisse), aber ich werde versuchen, für einen Moment damit zu spielen. –