按多个标签选择(白名单和黑名单)

时间:2015-09-14 22:12:45

标签: sql sqlite

我有以下结构:

CREATE TABLE stories
(
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  dir TEXT,
  alias TEXT,
  title TEXT
);

CREATE TABLE tags
(
  story_id INTEGER,
  name TEXT
);

现在我想选择所有(至少)给出N个标签的故事,并且没有其他N个标签。

示例:所有故事与"幻想"和#34;自然",但没有"龙"

这是我试过的一个查询(现在只是"白名单"部分,但它非常慢 - 所以我确定我做错了

SELECT s.*
FROM stories s
WHERE 
   (SELECT COUNT(*)
       FROM tags t
       WHERE 
           t.story_id = s.id
           AND t.name IN ('fantasy', 'nature')
   ) = 2

如果我添加" LIMIT 10"最后,它起作用(但非常缓慢)。

不知道如何将黑名单标准纳入查询中。

想法?

我有大约20,000个故事和75,000个标签条目。

1 个答案:

答案 0 :(得分:1)

这可以通过子查询轻松完成:

SELECT ...
FROM stories
WHERE id     IN (SELECT story_id FROM tags WHERE name = 'fantasy')
  AND id     IN (SELECT story_id FROM tags WHERE name = 'nature' )
  AND id NOT IN (SELECT story_id FROM tags WHERE name = 'dragons');

或者,使用compound query组合代码过滤器:

SELECT ...
FROM stories
WHERE id IN (SELECT story_id FROM tags WHERE name = 'fantasy'
             INTERSECT
             SELECT story_id FROM tags WHERE name = 'nature'
             EXCEPT
             SELECT story_id FROM tags WHERE name = 'dragons');

哪一个更快取决于您要检查的标签数量以及过滤器的选择性;你必须尝试。

如果tags.name列上有索引,则两个查询都有效。