如何解决从n:m关系中仅选择具有n关系的实体
我的数据库中的图像和标签具有m:n的关系,该关系使用交叉表对此建模。
表imgs
包含的信息远远不止img_id
,但这是唯一标识图像所需的全部信息。
我想找到每个同时包含tagA和tagB(以及tagC等)的img_id
,我将构建此字符串,因此,无论它是两个标签还是十个标签,都没有关系。
现在,我遇到的困难是,首先您要将imgs
与img_tags
与tags
结合在一起,为标记添加一个where子句;
SELECT *
FROM imgs
INNER JOIN img_tags ON imgs.img_id = img_tags.img_id
INNER JOIN tags ON img_tags.tag_id = tags.tag_id
WHERE tag = 'tagA' OR tag = 'tagB';
,然后您将获得具有相同的imgs
信息的行,仅在tag
和tag_id
上有所不同。现在,我应该能够计算出这些数量,只针对那些与提供的标签数量相同的商品(Count(*) = n
),然后使用group by
进行汇总?但是我不太清楚。
如果可能相关,则可以假定img_tags中的字段都是引用其他表的外键,但是不是这种情况,它们没有任何链接。
解决方法
以下是使用相关子查询的方法:
SELECT i.*
FROM imgs i
WHERE (
SELECT COUNT(*)
FROM img_tags it
INNER JOIN tags t ON it.tag_id = t.tag_id
WHERE i.img_id = it.img_id AND t.tag IN('tagA','tagB')
) = 2
这假定您的数据结构中没有重复的标签。否则,您可以使用COUNT(DISTINCT t.tag)
代替COUNT(*)
。
您还可以使用聚合:
SELECT i.id
FROM imgs i
INNER JOIN img_tags it ON i.img_id = it.img_id
INNER JOIN tags t ON it.tag_id = t.tag_id
WHERE t.tag IN('tagA','tagB')
GROUP BY i.id
HAVING COUNT(*) = 2
,
您可以像这样使用聚合:
SELECT i.*
FROM imgs i JOIN
img_tags it
ON i.img_id = it.img_id JOIN
tags t
ON it.tag_id = t.tag_id
WHERE tag IN ('tagA','tagB')
GROUP BY i.img_id
HAVING COUNT(*) = 2;
假设i.img_id
是表中的主键,按img_id
进行聚合是安全的-并且受到SQL标准的支持。
如果涉及的标签不多,我将为此使用现存的(或者如果您要排除一些标签则不存在)
select *
from imgs
where
exists(select 1 from img_tags it where it.tag_id=(select tag_id from tags where tag='tagA') and it.img_id=imgs.img_id)
and exists(select 1 from img_tags it where it.tag_id=(select tag_id from tags where tag='tagB') and it.img_id=imgs.img_id);
尤其是如果您最终想要执行更复杂的布尔表达式,例如(A和B,是否为C)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。