(为了清楚起见,在此提供极其简化的样本。)
我在数据库中有多对多关系(MySQL与Doctrine2 / Symfony2实体,但我想知道普通SQL中的答案),中间有一个简单的2列“连接表”:
项目
ID ITEMNAME
1 猫
2 鼠标
代码
ID 标记名
1 捕食者
2 食饵
3 喜欢奶酪
4 飞行
item_tag
ITEM_ID TAG_ID
1 1
1 3
2 2
2 3
此标准联接查询:
SELECT itemname, tagname FROM item
JOIN item_tag ON item_tag.item_id = item.id
JOIN tag ON item_tag.tag_id = tag.id
给我所有我感兴趣的数据,当然某些行是双倍的:
项目
ITEMNAME 标记名
猫 捕食者
Cat 喜欢奶酪
鼠标 食饵
鼠标 喜欢奶酪
现在我需要用一个简单的WHERE语句来过滤它,所以我添加了这样的东西:
WHERE tagname = 'prey'
但那只会返回一行。我需要为所有具有“猎物标记”的项目获取所有行 - 因此鼠标项的所有行都是如此。鼠标喜欢奶酪的事实是一个非常重要的细节,知道你什么时候寻找猎物!
关键当然是输入某个标签名称的搜索查询(事先不知道项目名称),但一旦它返回一组项目,我希望看到所有其他标签以及该组中的项目。
这可能是一个查询,还是我会被迫重新查询以获取剩余的相关标签?
答案 0 :(得分:1)
你可以从每个猎物那里得到item_id:
SELECT it.item_id
FROM item_tag it
JOIN tag t ON t.id = it.tag_id AND t.tagname = 'prey';
然后,您可以将其用作原始查询的`WHERE子句中的子查询,以获取这些项的所有行:
SELECT i.itemname, t.tagname
FROM item i
JOIN item_tag it ON it.item_id = i.id
JOIN tag t ON t.id = it.tag_id
WHERE i.id IN(
SELECT it.item_id
FROM item_tag it
JOIN tag t ON t.id = it.tag_id AND t.tagname = 'prey');
以下是SQL Fiddle示例。
答案 1 :(得分:0)
我认为我还包括我的Symfony2 / Doctrine解决方案,基于McAdam331对SQL的回答。
我在项目存储库中为子查询使用了第二个查询构建器实例。当然,您只需要使用与主查询构建器中使用的索引不同的索引。
$qb = $this->createQueryBuilder('i');
$sub = $this->createQueryBuilder('subi');
$search = $qb->expr()->orX(
$qb->expr()->like('i.name', ':s'),
$qb->expr()->in('i.id',
$sub->select('subi.id')
->join('subi.tags', 'subt')
->where($sub->expr()->like('subt.tagname',':s'))->getDQL()
),
... // various other search expressions are included in the OR clause
)
$qb->select('i','t')->join->('i.tags','t') // etcetera
->where($search)
->setParameter('s', "%".$searchString."%")