1

多くの投稿を見てきましたが、答えが得られませんでした構造を持つテーブルがあります

 subject_level_id  | tutor_id  | level_id_fk  | subject_id_fk |
  118              | 99        | 4            | 1             |
  119              | 99        | 3            | 2             |
  120              | 99        | 3            | 3             |
  121              |100        | 3            | 1             | 
  122              |100        | 4            | 2             |

特定のレベルの 1 つ、2 つ、またはそれ以上の科目を教える家庭教師のチューター ID を抽出したい (科目の数は、ユーザーが選択した科目によって異なりますが、レベルは特定のクエリに対して一意になります)

他の投稿の助けを借りてクエリを作成しましたが、チューターのレコードが 10,000 件あるため、被験者の数が 2 を超えると非常に遅くなり、悪化します。クエリは次のとおりです。

select distinct
   a.tutor_id
from
   tutor_preferred_level_subject as a
inner join
   tutor_preferred_level_subject as b
   on a.level_id_fk = b.level_id_fk
where
   a.subject_id_fk = 1 and
   b.subject_id_fk = 10 and
   a.level_id_fk = 3

提案:同じ列で複数の WHERE 条件を使用した SELECTING

この質問と私の質問の違いは、両方の科目を正確に教えてくれる家庭教師が欲しいということです。

更新: はい、主な関心事はパフォーマンスです。このクエリは 2 つのサブジェクトに対しては正常に機能しますが、2 つ以上のサブジェクトに対しては、mysql サーバーは永遠に処理を続けます。インデックスはsubject_level_idほぼ 13000 のレコードがあり、以下のクエリは約 6500 の結果を返します。

Jakub Sachaが要求したように、これらは次の結果です

EXPLAIN select distinct
   a.tutor_id
from
   tutor_preferred_level_subject as a
inner join
   tutor_preferred_level_subject as b
   on a.level_id_fk = b.level_id_fk
where
   a.subject_id_fk = 1 and
   b.subject_id_fk = 10 and
   a.level_id_fk = 3



id  select_type     table   type    possible_keys   key     key_len     ref|
1   SIMPLE          a   ALL     NULL            NULL    NULL            NULL 
1   SIMPLE          b   ALL     NULL            NULL    NULL           NULL 

rows    Extra 
12733   Using where; Using temporary
12733   Using where; Distinct
4

3 に答える 3

2

あなたのクエリはあなたが説明したことをしていないようです。結合はオンである必要があり、オンtutor_idではない必要がありますlevel_id_fk

組み合わせが一意でないDISTINCT場合にのみ必要です。(level_id_fk, subject_id_fk, tutor_id)

SELECT                              
    -- DISTINCT
   a.tutor_id
FROM
   tutor_preferred_level_subject AS a
INNER JOIN
   tutor_preferred_level_subject AS b
       ON a.tutor_id = b.tutor_id
WHERE
   a.subject_id_fk = 1 AND
   a.level_id_fk = 3 AND
   b.subject_id_fk = 10 AND
   b.level_id_fk = 3 ;

(level_id_fk, subject_id_fk, tutor_id)さらに、効率を上げるために(一意の)インデックスを追加する必要があります。

ALTER TABLE tutor_preferred_level_subject
  ADD INDEX level_subject_tutor_IDX
    (level_id_fk, subject_id_fk, tutor_id) ;
于 2013-01-03T07:50:57.137 に答える
1

これにより、(1、10)に一致する2つの異なるサブジェクトを持つすべてのtutor_idが選択されます。

SELECT
  Distinct tutor_id
FROM
  tutor_preferred_level_subject 
WHERE
  level_id_fk = 3
GROUP BY tutor_id, level_id_fk
HAVING
  Count(Distinct subject_id_fk) = 2 AND
  Sum(subject_id_fk NOT IN (1, 10)) = 0
于 2013-01-03T08:08:23.040 に答える
0

テーブルをそれ自体に内部結合する必要はないようです。これが、行が増えるにつれて速度が低下する原因となります。

あなたは「特定のレベルの 1 つ、2 つ、またはそれ以上の科目を教える家庭教師」が必要だと言いますが、これは基本的に、その特定のレベルを教える家庭教師が必要であることを意味します。したがって、グループ化して HAVING 句を使用してみてください(これにはもちろんデータがクリーンである必要があります)

SELECT a.tutor_id
FROM tutor_preferred_level_subject AS a
WHERE a.subject_id_fk IN (1,10)
  AND a.level_id_fk = 3
GROUP BY a.tutor_id
HAVING COUNT(1) > 1
于 2013-01-03T07:30:25.677 に答える