2009-07-30 9 views
1

非常にきちんとした解決策を持っていたこの質問SQL query that gives distinct results that match multiple columns に加えて、私は次のステップはどのように見えるかと思いまして:多対多のrealtionに対するMySQLのクエリ:共用体?

DOCUMENT_ID |  TAG 
---------------------------- 
    1  | tag1 
    1  | tag2 
    1  | tag3 
    2  | tag2 
    3  | tag1 
    3  | tag2 
    4  | tag1 
    5  | tag3 

ので、タグ1と2を持っているすべてのdocument_idsを取得するために、我々は、クエリを実行することになりは、

SELECT document_id 
FROM table 
WHERE tag = 'tag1' OR tag = 'tag2' 
GROUP BY document_id 
HAVING COUNT(DISTINCT tag) = 2 

さて、何を知るために興味深いものになるだろうが、我々はタグ1と2を持っているすべての個別document_idsになるだろうどのように、そして私たちは、想像タグ3 を持っていることに加えて、IDS:このような同じクエリを作成し、ユニオンベットを実行する

しかし、私はその条件が追加されていれば、別の初期クエリを考えることができるのだろうかと思っていました。私は、さまざまなタグとタグ数を持つような、多くの "ユニオン"を持つことを想像しています。 そのような組合の連鎖を作成することはパフォーマンス面で非常に悪くないでしょうか?

答えて

2

これはまだソートの和集合を使用しますが、読みやすく制御しやすくなります。私は本当に大規模なデータセットでこのクエリの速度に興味があるので、それがどれほど速いかを教えてください。あなたの小さなデータセットに入れたとき、それは0.0001秒かかりました。

SELECT DISTINCT (dt1.document_id) 
FROM 
    document_tag dt1, 
    (SELECT document_id 
    FROM document_tag 
    WHERE tag = 'tag1' 
) AS t1s, 
    (SELECT document_id 
    FROM document_tag 
    WHERE tag = 'tag2' 
) AS t2s, 
    (SELECT document_id 
    FROM document_tag 
    WHERE tag = 'tag3' 
) AS t3s 
WHERE 
    (dt1.document_id = t1s.document_id 
    AND dt1.document_id = t2s.document_id 
) 
    OR dt1.document_id = t3s.document_id 

これにより、タグごとに結果セットが指定されているため、新しいパラメータを簡単に追加できます。追加例えば

OR dt1.document_id = t2s.document_id 

終わりにもDOCUMENT_IDにピックアップします2

0

それは単一の中にこれを行うことは可能ですが、しかし、あなたがたにあなたのWHERE句を促進する必要があります継承を使用するには

0

UNION句に追加したい新しいタグを追加すると、それは遅くなり、遅くなります。各UNION句は、計画して実行する必要がある追加のクエリです。さらに、完了したらソートすることもできません。

基本的なデータウェアハウジング手法を探しています。まず、追加のテーブルを1つ追加してスキーマを再作成してみましょう。

create table a (document_id int, tag varchar(10)); 

insert into a values (1, 'tag1'), (1, 'tag2'), (1, 'tag3'), (2, 'tag2'), 
        (3, 'tag1'), (3, 'tag2'), (4, 'tag1'), (5, 'tag3'); 

create table b (tag_group_id int, tag varchar(10)); 

insert into b values (1, 'tag1'), (1, 'tag2'), (2, 'tag3'); 

表bには「タググループ」が含まれています。グループ1はtag1とtag2を含み、グループ2はtag3を含む。

今はあなたが興味のあるクエリを表現するために、テーブルbを変更することができ、あなたが照会する準備ができたら、あなたは集計データを保存するために一時テーブルを作成します。

create temporary table c 
(tag_group_id int, count_tags_in_group int, tags_in_group varchar(255)); 

insert into c 
select 
    tag_group_id, 
    count(tag), 
    group_concat(tag) 
from b 
group by tag_group_id; 

create temporary table d (document_id int, tag_group_id int, document_tag_count int); 

insert into d 
select 
    a.document_id, 
    b.tag_group_id, 
    count(a.tag) as document_tag_count 
from a 
inner join b on a.tag = b.tag 
group by a.document_id, b.tag_group_id; 

を今すぐcはのためのタグの数が含まれていますタグは、各文書が各タググループに対して有するタグの数を含む。 cの行がdの行と一致する場合、その文書はそのタググループ内のすべてのタグを持つことを意味します。このアプローチについて

select 
    d.document_id as "Document ID", 
    c.tags_in_group as "Matched Tag Group" 
from d 
inner join c on d.tag_group_id = c.tag_group_id 
      and d.document_tag_count = c.count_tags_in_group 

一つのクールなことは、あなたがこれらのタググループのそれぞれのタグの50%以上を持っているどのように多くの文書」のようなレポートを実行できることがありますか?'

select 
    d.document_id as "Document ID", 
    c.tags_in_group as "Matched Tag Group" 
from d 
inner join c on d.tag_group_id = c.tag_group_id 
      and d.document_tag_count >= 0.5 * c.count_tags_in_group