2011-08-05 14 views
0

私は複数のテーブルから選択するクエリに苦労してきました。私のオリジナルのクエリは非常に遅い(53秒)。読んでから、私は今、反復されるデータを制限するために内部クエリを作成する必要があることを合理的に確信しています。しかし、2つ以上のテーブルを使用する場合、サブクエリ(内部クエリ)の結果を使用する方法がわかりません。以下にいくつかのダミーのテーブルは以下のとおりです。私たちはそれぞれの休暇先のために一人一人のために別々の行を取得する場所MySQLのクエリを最適化する正しい方法

+-------+---------------------+------------+---------+---------+----------+ 
| tr_id | tr_datecreated  | tr_depart | p_name | p_lname | h_dest | 
+-------+---------------------+------------+---------+---------+----------+ 
|  1 | 2011-07-31 00:00:00 | 2011-08-20 | Geoff | Thingy | France | 
|  1 | 2011-07-31 00:00:00 | 2011-08-20 | Geoff | Thingy | Spain | 
|  1 | 2011-07-31 00:00:00 | 2011-08-20 | Mildred | Thingy | France | 
|  1 | 2011-07-31 00:00:00 | 2011-08-20 | Mildred | Thingy | Spain | 
|  1 | 2011-07-31 00:00:00 | 2011-08-20 | Garry | Thingy | France | 
|  1 | 2011-07-31 00:00:00 | 2011-08-20 | Garry | Thingy | Spain | 
|  2 | 2011-08-01 00:00:00 | 2011-08-30 | Linda | Doobrey | Italy | 
|  2 | 2011-08-01 00:00:00 | 2011-08-30 | Kev  | Doobrey | Italy | 
|  3 | 2011-08-02 00:00:00 | 2011-09-01 | John | Wotsit | Portugal | 
|  3 | 2011-08-02 00:00:00 | 2011-09-01 | Jill | Wotsit | Portugal | 
+-------+---------------------+------------+---------+---------+----------+ 

+-------+---------------------+------------+ 
| tr_id | tr_datecreated  | tr_depart | 
+-------+---------------------+------------+ 
|  1 | 2011-07-31 00:00:00 | 2011-08-20 | 
|  2 | 2011-08-01 00:00:00 | 2011-08-30 | 
|  3 | 2011-08-02 00:00:00 | 2011-09-01 | 
+-------+---------------------+------------+ 

+------+--------+---------+---------+ 
| p_id | p_trid | p_name | p_lname | 
+------+--------+---------+---------+ 
| 1 |  1 | Geoff | Thingy | 
| 2 |  1 | Mildred | Thingy | 
| 3 |  1 | Garry | Thingy | 
| 4 |  2 | Linda | Doobrey | 
| 5 |  2 | Kev  | Doobrey | 
| 6 |  3 | John | Wotsit | 
| 7 |  3 | Jill | Wotsit | 
+------+--------+---------+---------+ 

+------+--------+----------+ 
| h_id | h_trid | h_dest | 
+------+--------+----------+ 
| 1 |  1 | France | 
| 2 |  1 | Spain | 
| 3 |  2 | Italy | 
| 4 |  3 | Portugal | 
+------+--------+----------+ 

は、私のような結果を取得したいです。私は、これはクロスの膨大な数が加入し、クエリが非常にゆっくり走っ作成したことを考える

SELECT tr_id, tr_datecreated, tr_depart, p_name, p_lname, h_dest 
FROM transaction, people, holiday 
WHERE tr_id = p_trid 
AND tr_id = h_trid 
AND tr_datecreated >= "2010-12-12 00:00:00" 
AND tr_datecreated <= "2012-12-12 00:00:00" 

私のオリジナルの努力はの形をしていました。

tr_idが何回も参照されているのを見て、他のすべてが比較された行の数を減らした内側のクエリを実行したかったのです。

ので、内側のクエリの一部は次のようになります。

SELECT tr_id WHERE tr_datecreated >= "2010-12-12 00:00:00" 
AND tr_datecreated <= "2012-12-12 00:00:00" 

どのように私は(私はその倍の内側のクエリを実行することなく、同じ内部クエリに対するp_tridとh_tridの両方を比較したいと思う私の目的のテーブルを作成します可能なら)?

この状況で内部結合が役立つでしょうか? (私は読んだが、まだそれを完全に吸収していない)。

ここにアドバイスや提案をいただき、ありがとうございます。データベースは大きく、効率的である必要があります。

編集

インデックス:

tr_id、h_idとP_IDは

+----+-------------+--------------+--------+---------------+---------+---------+---------------------+------+--------------------------------+ 
| id | select_type | table  | type | possible_keys | key  | key_len | ref     | rows | Extra       | 
+----+-------------+--------------+--------+---------------+---------+---------+---------------------+------+--------------------------------+ 
| 1 | SIMPLE  | holiday  | ALL | NULL   | NULL | NULL | NULL    | 4 |        | 
| 1 | SIMPLE  | people  | ALL | NULL   | NULL | NULL | NULL    | 7 | Using where; Using join buffer | 
| 1 | SIMPLE  | transactions | eq_ref | PRIMARY  | PRIMARY | 4  | db.people.p_trid | 1 | Using where     | 
+----+-------------+--------------+--------+---------------+---------+---------+---------------------+------+--------------------------------+ 
+0

まず、インデックスヘルプを行います。テーブルの既存のインデックスとEXPLAINの出力を表示してください wonk0

+0

こんにちは。ご意見ありがとうございます。私は自分の投稿を編集しました。 – Joe

答えて

1

これはうまくいくと思います。それが動作するかどうか私に教えてください。

合計クエリ

SELECT t.id, t.date, t.depart, p.p_name, p.p_lname, h.h_dest 
FROM 
(SELECT tr_id 'id', tr_datecreated 'date', tr_depart 'depart' FROM transaction 
WHERE DATE(tr_datecreated) BETWEEN DATE("2010-12-12 00:00:00") 
AND DATE("2012-12-12 00:00:00")) t 
JOIN people p ON t.id = p.p_trid 
JOIN holiday h ON t.id = h.h_trid; 

内部クエリ

(SELECT tr_id 'id', tr_datecreated 'date', tr_depart 'depart' FROM transaction 
WHERE DATE(tr_datecreated) BETWEEN DATE("2010-12-12 00:00:00") 
AND DATE("2012-12-12 00:00:00")) 

編集:副問合せの説明

サブクエリが作成したID、日付を選択し、から列を出発のトランザクションテーブル上記の日付範囲。クエリ終了時の右側の括弧の外側にある 't'は、上記のデータを使用できるように内部クエリをエイリアスにします。また、サブクエリ内に'id''date''depart'のエイリアシングもあります。完全な列名を入力せずにこれらの値を使用できます。

これが役に立った。

+0

それはすばらしいおかげです。私はこれを徹底的に理解するために多くの時間を費やす必要があります。応答への歓声。 – Joe

+0

サブクエリで何が起こっているのかを編集して説明します –

+0

ハンターに感謝します。はい、それは多くの助けとなりました。 – Joe

1

は、あなたが加入しようとしているEXPLAINすべての主キーの

結果ですか?

SELECT tr.tr_id, tr.tr_datecreated, tr.tr_depart, p.p_name, p.p_lname, h.h_dest 
FROM transaction tr 
join people p on tr.tr_id = p.p_trid 
join holiday h on tr.tr_id = h.h_trid 
WHERE tr_datecreated >= "2010-12-12 00:00:00" 
AND tr_datecreated <= "2012-12-12 00:00 

これはまだテストされていませんが、それは一般的な考えです。

+0

これは彼が持っていたものです、彼はちょうど 'JOIN'キーワードを含まないことを選択しました –

1

people.p_tridとholiday.h_tridにインデックスを追加することをお勧めします。 EXPLAINは、両方の表に使用される索引がないことを明確に示しています。

また、transactions.tr_id、people.p_trid、およびholiday.h_tridのデータ型が同じであることを確認してください。