24

m2m 関係: items-categoriesを考えると、3 つのテーブルがあります。

  • アイテム,
  • カテゴリー
  • 両方への参照を保持するitems_categories

指定されたすべてのカテゴリセットに属するアイテムを見つけたい:

Find Item 
belonging to a category in [1,3,6] 
and belonging to a category in [7,8,4] 
and belonging to a category in [12,66,42]
and ...

mySQL でこれを実現するには、2 つの方法が考えられます。

オプション A: 内部結合:

SELECT id from items 
INNER JOIN category c1 ON (item.id = c1.item_id)
INNER JOIN category c2 ON (item.id = c2.item_id)
INNER JOIN category c3 ON (item.id = c3.item_id)
...
WHERE
c1.category_id IN [1,3,6] AND
c2.category_id IN [7,8,4] AND
c3.category_id IN [12,66,42] AND
...;

オプション B: 存在する:

SELECT id from items
WHERE
EXISTS(SELECT category_id FROM category WHERE category.item_id = id AND category_id in [1,3,6] AND
EXISTS(SELECT category_id FROM category WHERE category.item_id = id AND category_id in [7,8,4] AND
EXISTS(SELECT category_id FROM category WHERE category.item_id = id AND category_id in [12,66,42] AND
...;

どちらのオプションも機能します。質問は次のとおりです。大きな項目テーブルで最も高速/最適なのはどれですか? または、欠落している OPTION CI がありますか?

4

5 に答える 5

15

一般的に言えば、 A のJOIN方が効率的です。

ただし、結合によって出力に重複する行が生成される可能性があることに注意してください。たとえば、アイテム ID がカテゴリ 1 と 3 にある場合、最初のJOIN行は ID 123 の 2 行になります。アイテム ID 999 がカテゴリ 1、3、7、8、12、および 66 にある場合、8行になります。結果で 999 (2*2*2)。

重複行は、認識して処理する必要があるものです。この場合、そのまま使用できますselect distinct id...。ただし、重複を排除することは、複雑なクエリではより複雑になる可能性があります。

于 2012-10-25T07:51:32.747 に答える
15

オプションA

JOINEXIST特に大きなテーブルの場合、インデックスをより効率的に使用するため、 よりも利点があります。

于 2012-10-25T07:40:42.517 に答える
2

オプション AでJoin を使用し、オプション Bサブクエリを使用しています。違いは次のとおりです。

ほとんどの場合、JOIN はサブクエリよりも高速であり、サブクエリが高速であることは非常にまれです。

JOIN では、RDBMS はクエリに適した実行計画を作成し、処理のためにどのデータをロードする必要があるかを予測して時​​間を節約できます。これは、すべてのクエリを実行し、すべてのデータをロードして処理を行うサブクエリとは異なります。 .

サブクエリの良いところは、JOIN よりも読みやすいことです。これが、ほとんどの SQL 初心者がサブクエリを好む理由です。それは簡単な方法です。しかし、パフォーマンスに関しては、ほとんどの場合、JOINS の方が読みにくいわけではありませんが、より優れています。

于 2012-10-25T07:43:13.910 に答える