2012-02-29 9 views
1

基本的に、私がしたいことは、ある誕生年の間に他のテーブルのすべての子を取得することです。だから私は2つのテーブルを持っています。のは、それがこのメインクエリでサブクエリの結果を使用するMysql

SELECT *, (SELECT COUNT(*) FROM school LEFT JOIN children ON school.child_id = children.child_id) as total FROM school LEFT JOIN children ON school.child_id = children.child_id GROUP BY birth_year 

のようなものである学校のテーブル

学校

school_id 
child_id 

子供

child_id 
birth_year 
name 
etc 

私の最初の試みは、サブクエリを使用することで、だとしましょうこの問合せの問題は、サブクエリがレコード全体で実行されるため、1000レコードがある場合、birth_yearでグループ化する前に1000回実行すると思います(遅いですが、ほぼ3〜5秒です)。 500サンプルデータ。

これを最適化するために、私はこれをやっています。

まずPHPを使用して

再帰クエリは、学校内にあるすべての子どもの個別の誕生年を取得します。だから私はそれは私がPHPで別のクエリでつもり利用だ

birth_year 
========== 
2009 
2010 
2011 

のようなデータを返します

SELECT birth_year FROM school LEFT JOIN children ON school.child_id = children.child_id 

のようなつもりクエリ何かだ(のは、私は$行の結果を変数に格納するとしましょう)

foreach ($row as $r){ 
    $new_array[] = count($this->db->get_child_data($r->birth_year)); //this is pseudocode only, to get the number of children data who have birth_year of 2009-2011 
} 

追加の3つのクエリが実行されますが、これはカウントが単純なので非常に高速です。 500サンプルデータでは0.5秒未満しかかかりません。

しかし、それを最適化する方法があるのでしょうか?それとも、同様のパフォーマンスを持つ1つのクエリでそれを行う方法はありますか?

私はこれをやろうとしていますが、それは非常に遅くなり、私のWAMPをクラッシュさせます。

SELECT * FROM children WHERE birth_year IN (SELECT GROUP_CONCAT(DISTINCT birth_year) FROM school LEFT JOIN children ON school.child_id = children.child_id) 

サブクエリ

SELECT GROUP_CONCAT(DISTINCT birth_year) FROM school LEFT JOIN children ON school.child_id = children.child_id 

別途正しく実行し、迅速

2009,2010,2011 

を返し、私は

SELECT * FROM children WHERE birth_year IN (2009,2010,2011) 

を照会する場合それはまた、高速に動作するので、私は私が両方のクエリーに参加するとき、なぜ非常に混乱した私のWAMPをクラッシュさせるのは遅いです。

事前に長い記事と感謝のために申し訳ありません

答えて

2

問題がINまたはSELECT句でサブクエリを使用すると、多くの場合、外側のクエリの各行のために再度実行されるようにそれらを引き起こすことがあります。これを避けるには、サブクエリに参加してみてください。これにより、サブクエリは1回だけ実行され、キャッシュされます。あなたがちょうどそう単純で登録しよう、とにかくどの学校ですべての子供を取得しているように見える、と述べ

SELECT c.* 
FROM children c, (SELECT birth_year FROM school LEFT JOIN children ON school.child_id = children.child_id GROUP BY birth_year) b 
WHERE c.birth_year = b.birth_year 

はまた、あなたと同じ結果を与えるかもしれません。

SELECT c.* 
FROM children c, school s 
WHERE c.child_id = s.child_id 

あなただけの各birth_yearのために、各学校での子供の数を取得したい場合は

SELECT count(c.child_id), s.* 
FROM school s 
LEFT JOIN children c ON c.child_id = s.child_id 
GROUP BY s.school_id, c.birth_year 
+0

実際に私はubquery、私は毎年子供の合計を取得したいので、私の最初の試みを見てください。しかし、ボトルネックはカウントサブクエリのように思えます... – Henson

+0

ここのキーはサブクエリの場所です。しかし、私は言わなければならない、あなたの最終目標が何であるかははっきりとは分かりません。 – Umbrella

+0

私は再帰的なPHPクエリに行くと思う、速くて、私は約4秒(サブクエリ)対0.2秒(再帰的なPHP)を話している。あなたは正しい、私の最終目標は毎年学校で子供の合計を取得することです、それを行う最も簡単な方法は、PHPがハードワークを行うことができますように再帰的なクエリです – Henson

-1

あなたが生まれた年に子どもの数を取得しようとしている場合

SELECT COUNT (c.child_id) FROM child c INNER JOIN school s ON (c.child_id = s.child_id) GROUP BY birthyear 

追加のフィルタが必要な場合は、必要な年のwhere句を追加することができます

+0

私は私の最初の試み:SELECT *、(学校から子供の数を選択(*)、左の子供たちはschool.child_id = children.child_id)を学校の子供たちと一緒にLEFT JOINしてみましょう.child_id = children.child_id GROUP BY birth_yearは遅いです。サブクエリーで子どもと一緒に学校に入学することは、より正確な結果を得るために必要であると考えています(学校にいない子供は含まれていません) – Henson

関連する問題