2012-04-01 13 views
8

私はちょっと固まっているようです。これはまったく簡単なクエリです。サブクエリでグループを最適化するために必要なMysqlのヘルプ

私が別々にクエリを実行すると、それは遅くはないが、それらを組み合わせると非常に遅くなる。

私はそれを最適化する方法がわかりません。どんな助けでも大歓迎です。私は基本的に、複数の払い戻しを表示したいだけです。だからfaultidが複数回存在する。説明から

SELECT 
    r.* 
FROM 
    faultrefunds_v2 r 
WHERE 
    r.id IN (SELECT r1.id 
      FROM faultrefunds_v2 r1 
      GROUP BY faultid 
      HAVING count(r1.faultid) > 1); 

結果は、私はあなたのクエリが質問に答えていないと思う画像

enter image description here

+0

r.idがprimarですyキー? –

+0

はい、faultidは外部キーです –

+0

あなたが書いたクエリは質問に答えないと思います。これは、あなたがfaultidでグループ化すると、そのfaultidに対して1つのr.idしか返さないからです。 –

答えて

1

を私は推測する、これは、より再書き込みとしてではなく資格とにかく私が代わりに試してみたいのはこれです:

SELECT 
    r.* 
FROM faultrefunds_v2 r 
WHERE EXISTS (
    SELECT * 
    FROM faultrefunds_v2 r1 
    WHERE r1.faultid = r.faultid 
    AND r1.id <> r.id 
); 
+0

これも機能しました。 –

+0

なぜこれは私が書いたクエリよりもずっと速いのですか?彼らはかなり似ていますか? –

+1

クエリでは、比較的高価な操作であるグルーピングが使用されます。さらに、その種のサブクエリは、テーブル全体をスキャンして一致する行セットを作成することになっています。一方、私のクエリは、(EXISTS述語の形で)半結合を使用します。セミジョインでは、少なくとも1つが見つかると直ちに行停止が検索されます。これは、行の一部または大半が多数一致する場合にクエリを大幅に高速化する可能性があります。 –

1

として添付されているされています。私が理解しているように、あなたはまず、複数の関連ID(テーブル内の行)を持つすべてのfaultidを取得する必要があります。そして、すべての行(faultIdだけでなく)を取得します。

これを試してください:あなたはそれが非常に遅くなります使用

select * from faultrefunds_v2 
where faultId in (
    select faultId from faultrefunds_v2 
    group by faultId 
    having count(*) > 1 
) 
+0

これは私のクエリが改善されたと思います。論理的で説明的です。しかし、それはまだかなり遅いです。それは+1 –

2

IN句の方法は、代わりにJOINを使用します。

SELECT r.* FROM ( 
    SELECT r1.id AS id 
    FROM faultrefunds_v2 r1 
    GROUP BY faultid 
    HAVING count(r1.faultid) > 1 
) AS ids 
LEFT JOIN faultrefunds_v2 AS r 
ON(ids.id = r.id) 
+0

を与え、これは非常に高速です。あなたはIN句がなぜ私がそれを使っている方法で遅いのかを説明して、もう一度やることを避けることができますか? –

+1

MySqlは通常、IN句内の要素を索引付けしないので、 'r'表の各行のidと毎回サブ問合せで見つかったすべてのIDを比較する必要があります。 MySqlのメソッドでは、MySqlはすべての適切なIDを一度検出してから、インデックスを使用して非常にすばやく外側のクエリの各IDに対して完全な行を取得します。 – nobody

+0

この回答はAndiry Mの回答に沿った正解です。私は2つの答えを受け入れることはできません(しかし、同じ質問に対して2つの正しい答えを持つことは可能です)。 –

関連する問題