2

私はデータベース プログラマーではありませんが、タグ付きの項目を持つシンプルなデータベース ベースのアプリを持っています。各アイテムには複数のタグがある可能性があるため、(このような) 典型的なジャンクション テーブルを使用しています。各行は、適切な ID を持つアイテムに適切な ID を持つタグがあるという事実を表します。

特定のタグを持つすべてのアイテムを選択するようなことをしたい場合、これは非常に論理的に機能します。

しかし、検索を行うための典型的なパターンは何ですか? ANDつまり、特定のタグのセットをすべて持つすべてのアイテムを検索したい場合はどうすればよいでしょうか? これは非常に一般的な操作なので、いくつかのイントロ チュートリアルで説明されていると思いますが、適切な場所を探していないと思います。

私が試したアプローチはINTERSECT、最初に直接、次にサブクエリとを使用することでしたIN。これは機能しますが、検索用語を追加すると、長く見えるクエリがすぐに作成されます。そして、重要なことに、このアプローチは、すべてのタグをテキストとして 1 つの「タグ」列に押し込み、SQLite の全文検索を使用するアプローチよりも約 1 桁遅いようです。(そして、私が期待/希望しているように、FTS 検索は用語を追加するにつれて高速になりますが、これは INTERSECTS アプローチには当てはまらないようです。)

ここでの適切なデザイン パターンは何ですか。この場合、私は SQLite を使用していますが、これよくあることなので、一般的な回答に最も関心があります。

4

2 に答える 2

2

以下は、ID の数と ID 自体の同期を回避する標準の ANSI SQL ソリューションです。

with tag_ids (tid) as (
   values (1), (2)
)
select id
from tags
where id (select tid from tag_ids)
having count(*) = (select count(*) from tag_ids);

values節 (「行コンストラクター」) は、PostgreSQL と DB2 でサポートされています。それをサポートしていないデータベースの場合、単純な「選択」に置き換えることができます。たとえば、Oracle では次のようになります。

with tag_ids (tid) as (
   select 1 as tid from dual
   union all 
   select 2 from dual
)
select id
from tags
where id (select tid from tag_ids)
having count(*) = (select count(*) from tag_ids);

SQL Server の場合はFROMSELECT.

これは、1 つのタグを 1 回だけ割り当てることができることを前提としています。そうでない場合はcount(distinct id)having句で a を使用する必要があります。

于 2012-08-20T21:33:38.127 に答える
1

次の方法でグループを使用する傾向があります。

select id
from tags
where id in (<tag1>, <tag2>)
group by id
having count(*) = 2

これにより、両方が表示されることが保証されます。

無制限のサイズのリストの場合、'|tag1|tag2|tag3|' のように ID を文字列に格納できます。(末尾の区切り記号に注意してください)。次に、次のことができます。

select id
from tags
where @taglist like '%|'+tag+'|%'
group by id
having count(*) = len(@taglist) - (len(replace(@taglist, '|', '') - 1)

これは SQL Server 構文を使用しています。しかし、それは2つのことを言っています。WHERE 句は、タグがリストにあることを示しています。HAVING 句は、一致の数がリストの長さと等しいことを示しています。これは、セパレータの数を数えて 1 を引くというトリックで行われます。

于 2012-08-20T18:57:24.230 に答える