2017-11-09 6 views
0

私は1対多の関係を持つデータベースを持っています。 AND ONLY tag.valueの特定のリストにリンクされているsqlite 1〜多くのスキーマ:itemXとitemYにのみリンクされたクエリ行

  • :私はそれがidFileのリストを取得するために照会することができますどのように

    CREATE TABLE 'tag' (
        'id' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 
        'value' TEXT NOT NULL, 
        CONSTRAINT name_unique UNIQUE ('value') 
    ); 
    
    CREATE TABLE 'tagfile' (
        'idFile' INTEGER NOT NULL, 
        'idTag' INTEGER NOT NULL, 
        PRIMARY KEY ('idFile', 'idTag'), 
        FOREIGN KEY(idFile) REFERENCES tracks(ID), 
        FOREIGN KEY(idTag) REFERENCES tag(id) ON DELETE CASCADE 
    ); 
    

    ? (タグテーブルからの他のデータへのリンクを持つidFileを避ける)

  • tag.valueの指定されたリストに少なくともリンクされていますか?あなたがgroup byhavingを使用することができます
+0

カラム名を一重引用符で囲まないでください。 SQLiteが状況によってはそれを受け入れるとしても、それは本当に悪い習慣です。 –

答えて

1

(idFileは、タグテーブルから他のデータへのリンクを持つことができるよう):

select tf.idFile 
from tagfile tf join 
    tag t 
    on tf.idtag = t.id 
where t.value in ('a', 'b', 'c') 
group by tf.idFile 
having count(*) = 3; -- length of list 

あなたはこれらの3つなどを持つファイルをしたい場合は、上記を使用します。あなたは正確にこれらの3つたい場合:

select tf.idFile 
from tagfile tf join 
    tag t 
    on tf.idtag = t.id 
group by tf.idFile 
having sum(case when t.value in ('a', 'b', 'c') then 1 else 0 end) = 3 and 
     count(*) = 3; -- length of list 
+0

良いアイデア。ありがとう。他の人のためのアイデア(AT LEASTまで)? – phramusca

+0

Humm、count(*)> = 3;すべきだ! – phramusca

+0

count(*)> = 3の3つの項目は要求されたものと異なる可能性があるので、トリックではありません:( – phramusca

0

(私の場合は大したまたはいくつかの奇妙な結果が発生する可能性がありますがない)、それは重複しないタグを必要とするものの、このソリューションを使用して終了。 誰もがしかし、より良いクエリを持っている場合、私は:)

select tf.idFile, GROUP_CONCAT(t.value) AS tags 
from tagfile tf join 
    tag t 
    on tf.idtag = t.id 
group by tf.idFile 
having tags LIKE "%a%" 
AND tags LIKE "%b%" 
AND tags LIKE "%c%" 
AND tags NOT LIKE "%d%" -- to filter out 

編集から聞いて喜んでいると思います。最後にゴードンからのソリューションを使用して

select tf.idFile, GROUP_CONCAT(t.value) AS tags 
from tagfile tf join 
    tag t 
    on tf.idtag = t.id 
group by tf.idFile 
-- Those to include: (= length of include list) 
having sum(case when t.value in ('a', 'b', 'c') then 1 else 0 end) = 3 
-- Those to exclude: (= 0) 
and sum(case when t.value in ('z', 'y') then 1 else 0 end) = 0   
-- for exact list match, add: 
-- and count(*) = 3 -- (= length of include list) 
関連する問題