2012-04-17 14 views
2

背景:私は自分の画像のコレクションを管理するための自家製プロジェクトに取り組んでおり、タグベースの検索を実装しようとしています。"タグ"検索/除外クエリデザインの問題

今、各イメージのデータベースエントリにタグを適用するためのRedBeanのタグ付けAPIを使用していますが、実装の具体的な詳細がわかりません。現在、(「ABC XYZ」を検索する際、タグ付けされた画像は、タグ「ABC」「XYZ」を持っている必要があります)

を複数のタグ検索を絞り込むますタグの検索を可能にするために、私はいくつかを処理するために抱えています(オプション)2番目のクエリを実行して、返されたイメージに結果から明示的に除外されたタグがないことを確認します。 (「ABC -XYZ」を検索する場合、タグ付き画像はタグ「ABC」とでなく、「XYZ」でなくてはなりません)。

ここでの問題は、現在の方法ではすべての結果をサーバーサイドコードで実行する必要があり、わかりやすいページ区切り/結果オフセットの試行が不正確になります。

私の目標は、1つのクエリで要求されたタグを含む(除外タグを含まない)postテーブルの行をちょうど掴んで、依然としてLIMIT/OFFSET引数を使用して合理的にページ単位にすることです結果。

表のスキーマは次のとおりです。

Table "post" 
Columns: 
    id (PRIMARY KEY for post table) 
    (image metadata, not relevant to tag search) 

Table "tag" 
Columns: 
    id (PRIMARY KEY for tag table) 
    title (string of varying length - assume varchar(255)) 

Table "post_tag" 
Columns: 
    id (PRIMARY KEY for post_tag table) 
    post_id (associated with column "post.id") 
    tag_id (associated with column "tag.id") 

可能であれば、私はまた、同様post表の列にWHERE条件は、特定の持ってできるようにしたいと思います。

クエリ構造にはどのようなものを使用しますか?私は左の結合で遊んできましたが、これを解決するために必要な正確な構造を得ることができませんでした。ここで

答えて

2

は、基本的な考え方です:

LEFT OUTER JOINは除外したいタグに一致する記事のセットです。クエリの最後のWHERE句は、これらの投稿のどれも最初のpostテーブルのエントリと一致しないことを確認します。

INNER JOINは、すべてのタグに一致する投稿セットです。数字2は、IN句で指定した一意のタグ名の数と一致しなければならないことに注意してください。

select p.* 
from post p 
left outer join (
    select pt.post_id  
    from post_tag pt 
    inner join tag t on pt.tag_id = t.id 
    where t.title in ('UVW', 'XYZ') 
) notag on p.id = notag.post_id 
inner join (
    select pt.post_id  
    from post_tag pt 
    inner join tag t on pt.tag_id = t.id 
    where t.title in ('ABC', 'DEF') 
    group by pt.post_id 
    having count(distinct t.title) = 2 
) yestag on p.id = yestag.post_id 
where notag.post_id is null 
--add additional WHERE filters here as needed 
+0

SQLiteでは動作しないようですが、行は返されません。私はテストベッドDBをMySQLに素早くマイグレーションし、それがどのようになっているかを見ていきます。 – damianb

+0

MySQLのサイコロもありません。テストベッドdbには、(abc、def、ghi)タグ付きの2つのポストと、他のタグ付き(abc、def、xyz)の2つのポストがありました。 '(" xyz ")'の除外/左外部結合と結果のない '(" abc "、" def ")の検索/内部結合を使ってクエリを試してみました。私は構造をちょっと調べて、どこが怒っているのか分かりますか? – damianb

+0

は "explain"を使ってクエリを実行しましたが、最初のチャンクにはこれがあります: "constテーブルを読んだ後に気付かれなかったWHERE"。 – damianb