我有一个非常简单的标记系统,用于我的视频收藏,我正在使用它使用SQLite。我正在努力实现让我感到困惑的一项功能。我希望能够使用“包含/排除”池来检索视频。 IE:
我的结构如下:
目前,我可以使用以下查询来提取带有标签的所有视频:
SELECT Media.filename FROM Tags
INNER JOIN Media_Tags ON Tags.id = Media_Tags.tag_id
INNER JOIN Media ON Media_Tags.media_id = Media.id
WHERE Tags.name = 'people'
我试图做的是表演:
SELECT Media.filename FROM Tags
INNER JOIN Media_Tags ON Tags.id = Media_Tags.tag_id
INNER JOIN Media ON Media_Tags.media_id = Media.id
WHERE Tags.name = 'people'
AND Tags.name = 'seinfeld'
AND Tags.name != 'elaine'
AND Tags.name != 'george'
当我看到我正在检索标签的所有视频而不是视频的所有标签时,问题变得很明显,因此,该操作始终返回零记录。在这一点上,我不确定是否要重写此查询。
有人可以为我提供一些有关如何实现这一目标的指导吗?
答案 0 :(得分:2)
您可以通过聚合和having
来做到这一点:
SELECT m.filename
FROM Tags t INNER JOIN
Media_Tags mt
ON t.id = mt.tag_id INNER JOIN
Media m
ON mt.media_id = m.id
GROUP BY m.filename
HAVING SUM(CASE WHEN t.name = 'people' THEN 1 ELSE 0 END) > 0 AND
SUM(CASE WHEN t.name = 'seinfeld' THEN 1 ELSE 0 END) > 0 AND
SUM(CASE WHEN t.name = 'elaine' THEN 1 ELSE 0 END) = 0 AND
SUM(CASE WHEN t.name = 'george' THEN 1 ELSE 0 END) = 0 ;
HAVING
子句中的每个条件都会为每个filename
上的每个标签测试一个条件。 > 0
表示该标签存在; = 0
说该标签不存在。
您的原始问题的回答方式也相同:
HAVING SUM(CASE WHEN t.name = 'nature' THEN 1 ELSE 0 END) > 0 AND
SUM(CASE WHEN t.name = 'grass' THEN 1 ELSE 0 END) > 0 AND
SUM(CASE WHEN t.name = 'sky' THEN 1 ELSE 0 END) > 0 AND
SUM(CASE WHEN t.name = 'horror' THEN 1 ELSE 0 END) = 0 AND
SUM(CASE WHEN t.name = 'gore' THEN 1 ELSE 0 END) = 0 ;