MySQL:如果连接表中的列包含x,则选择具有相同ID的所有行

时间:2015-07-02 13:14:34

标签: mysql join many-to-many where-clause

(为了清楚起见,在此提供极其简化的样本。)

我在数据库中有多对多关系(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'

但那只会返回一行。我需要为所有具有“猎物标记”的项目获取所有行 - 因此鼠标项的所有行都是如此。鼠标喜欢奶酪的事实是一个非常重要的细节,知道你什么时候寻找猎物!

关键当然是输入某个标签名称的搜索查询(事先不知道项目名称),但一旦它返回一组项目,我希望看到所有其他标签以及该组中的项目。

这可能是一个查询,还是我会被迫重新查询以获取剩余的相关标签?

2 个答案:

答案 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."%")