2016-08-08 9 views
3

には1対多の関係を持つ2つのテーブルがあります。MAX(date)<X

Table1 
ID name email 
Table2 
ID table1_ID date 

私は表1 whereからすべてのデータを取得する必要があります。

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

これは動作しません。 Maxはwhere句で「無効」とみなされます。私がしたことは:

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) 

です。しかし、パフォーマンスはひどくなると思います。explainは、すべてTable2が読み取られていることを示しています。この表は大きく成長します。

どうやってそれをやり遂げることができるか、現在のクエリのパフォーマンスを改善する方法はありますか?

+0

なぜパフォーマンスはひどいと思いますか? –

+1

テーブル2にtmpを結合する中間ステップを含めるのではなく、テーブル1にtmpに参加するのはちょっと奇妙です。また、WHERE句をサブクエリに配置します。それ以外にも、索引付けされているので、このクエリは慌てて速くなるはずです。 – Strawberry

+1

'MAX(date)'は集約であるため、 'WHERE'に入れることはできませんが、代わりに' HAVING'に属します。とにかく、他の人が指摘しているように、 'MAX(HAVING MAX) 'の代わりに' 2016-01-01'を使うと、 'WHERE date> '2016-01-01'を使うことができます。 –

答えて

2

試してみてください。

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) 

する前に、あなただけの表2から皆を戻すと、表1でそれに参加します。これは、maxdate> "2016-01-01"なしですべてのものをノックオフし、Table1でそれに参加します。

+0

それは非常に良い点です、@Strawberryもコメントでそれを指摘した、ありがとう! –

1

まず、テストあなた自身でチェックしてください。

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>) 

あなたはまた、あなたのサブクエリ内table2.date > "2016-01-01"を追加することができます。

第二に、あなたは表2をフィルタリングし、GROUP BY句を使用することはできませんbecuase少し速くなる可能性があるEXISTS()を使用して試すことができます。

また、次のインデックスを追加することを検討:追加の条件がある場合、私はあなたが提供したクエリに基づいてこれらのインデックスをお勧めします

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

注意を、このインデックスは、完全ではないかもしれません。

+0

こんにちは、ありがとう!もちろん、インデックスは適切に設定されています。あなたは非常に興味深い点があります。私はそれが本当に他の必須のポイント(maxdate、制限結果セットで注文)に合っているとは思わないが、私はそれをしばらく試してみるだろう。 –

関連する問題