使用MySQL,是否有一种通过检查关联表上是否存在多行来过滤一个表上的记录的有效方法?
例如,我有一个图像表和另一个表识别该图像中对象的表:
table: images
id | url
----+--------------------------------
1 | http://www.example.com/foo.png
2 | http://www.example.com/bar.png
3 | http://www.example.com/baz.png
table: image_tags
image_id | tag
----------+-------------
1 | cats
1 | living-room
2 | beach
2 | towel
2 | dogs
3 | cats
3 | dogs
3 | goldfish
如果我想查询包含cats
和dogs
的所有图片,那么最好的方法是什么?如果我想要的图片包含cats
,dogs
和goldfish
?
我尝试过的一种方法是查询包含狗的所有image_ids
图像,然后查询包含猫的图像,然后选择交叉点。我可以在我的应用程序中执行此操作,但我想知道是否有办法使用SQL处理任意数量的标记来运行相同的操作。
答案 0 :(得分:1)
我喜欢使用having
和select it.image_id
from image_tags it
where it.tag in ('cats', 'dogs')
group by it.image_id
having count(*) = 2;
来处理这些类型的查询(" set-within-set"查询):
in
注意" 2"需要等于func functionX(collection []*interface{}) {
...
response, err := json.MarshalIndent(collection, "", " ")
...
}
列表中要匹配的标签数量。
答案 1 :(得分:0)
另一种选择,虽然比戈登的回答更加冗长但也许更高效(?? - 抱歉没有MySQL测试):
select i.id, i.url from images i where exists(
select 1 from image_tags g where g.image_id=i.id and g.tag='cats'
)
and exists(
select 1 from image_tags g where g.image_id=i.id and g.tag='dogs'
)
答案 2 :(得分:0)
如果您可以将列表作为逗号分隔的字符串提供,这应该可以工作(但它可能无法很好地转换为正确规范化的表结构):
SET @tagCount := 1 + LENGTH([csvstring]) - LENGTH(REPLACE([csvstring], ',', '');
SELECT it.image_id, SUM(IF(FIND_IN_SET(it.tag, [csvstring])=0,0,1)) AS matches
FROM image_tags AS it
HAVING matches = @tagCount
;
或者......
SET @tagCount := 1 + LENGTH([csvstring]) - LENGTH(REPLACE([csvstring], ',', '');
SELECT it.image_id, COUNT(1) AS matches
FROM image_tags AS it
WHERE FIND_IN_SET(it.tag, [csvstring]) > 0
GROUP BY it.image_id
HAVING matches = @tagCount
;
采用更规范化的结构,这可能是一个不错的选择:
SELECT it.image_id, COUNT(1) AS matches
FROM tags AS t
INNER JOIN image_tags AS it USING (tag_id)
WHERE FIND_IN_SET(t.tag_string, [csvstring]) > 0
GROUP BY it.image_id
HAVING matches = @tagCount
;
答案 3 :(得分:0)
这是一个“Scuttle”解决方案
http://tagging.pui.ch/post/37027745720/tags-database-schemas
和
SELECT b。* 来自scBookmarks b,scCategories c 在哪里c.bId = b.bId AND(c.category IN(' bookmark',' webservice',' semweb')) GROUP BY b.bId 有COUNT(b.bId)= 3
或者
SELECT b。* 来自scBookmarks b,scCategories c 在哪里c.bId = b.bId AND(c.category IN(' bookmark',' webservice',' semweb')) GROUP BY b.bId
减去
选择b。 * 来自scBookmarks b,scCategories c 在哪里b.bId = c.bId AND(c.category IN(' bookmark',' webservice')) 和b.bId没有 IN(选择b.bId来自scBookmarks b,scCategories c WHERE b.bId = c.bId AND c.category =' semweb') GROUP BY b.bId 有计数(b.bId)= 2
这些代码示例直接来自网站。您需要相应调整