简体   繁体   English

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

[英]MySQL: Select all rows with the same ID, if a column from a joined table contains x

(Giving an extremely simplified sample here, for the sake of clarity.) (为清楚起见,此处提供了一个极为简化的示例。)

I have a many-to-many relationship in a database (MySQL with Doctrine2/Symfony2 entities, but i'd like to know the answer in plain SQL), with a simple 2-column "join table" in between: 我在一个数据库中有一个多对多关系(带有Doctrine2 / Symfony2实体的MySQL,但我想知道普通SQL中的答案),并且在它们之间有一个简单的2列“联接表”:

item 项目
id itemname ID ITEMNAME
1 Cat 1 只猫
2 Mouse 2只 老鼠

tag 标签
id tagname id 标记名
1 Predator 1 捕食者
2 Prey 2 猎物
3 Likes Cheese 3 Likes奶酪
4 Flying 4 飞行

item_tag item_tag
item_id tag_id item_id tag_id
1 1 1 1
1 3 1 3
2 2 2 2
2 3 2 3

The standard join query for this: 为此的标准联接查询:

SELECT itemname, tagname FROM item
JOIN item_tag ON  item_tag.item_id = item.id
JOIN tag ON item_tag.tag_id = tag.id

gives me all the data i'm interested in, with certain rows being double of course: 给我我感兴趣的所有数据,某些行当然是两倍:

item 项目
itemname tagname 项目名称 标记名
Cat Predator 捕食者
Cat Likes Cheese 喜欢奶酪
Mouse Prey 老鼠 猎物
Mouse Likes Cheese 老鼠 喜欢奶酪

Now I need to filter this with a simple WHERE statement, so I add something like this: 现在,我需要使用简单的WHERE语句对此进行过滤,因此我需要添加以下内容:

WHERE tagname = 'prey'

But that only returns a single row of course. 但这当然只返回一行。 I need to get all rows for all items which have a 'prey tag' — so all the rows for the mouse item. 我需要获取所有带有“猎物标签”的项目的所有行-因此鼠标项目的所有行。 The fact that the mouse likes cheese is a pretty important detail to know when you are searching for prey! 鼠标喜欢奶酪的事实是您寻找猎物时要知道的一个非常重要的细节!

The point is of course to enter a search query for a certain tag name (without knowing the item names in advance), but once it returns a set of items, I would like to see all the other tags as well for the items in that set. 重点当然是要输入针对特定标签名称的搜索查询(不事先知道商品名称),但是一旦它返回一组商品,我也希望查看该商品中的所有其他标签组。

Is this possible with one query, or would I be forced to re-query to grab the remaining associated tags? 一个查询是否可能做到这一点,还是我将不得不重新查询以获取其余的关联标签?

You can get the item_id from each prey like this: 您可以像这样从每个猎物获取item_id:

SELECT it.item_id
FROM item_tag it
JOIN tag t ON t.id = it.tag_id AND t.tagname = 'prey';

Then, you can use that as a subquery in the `WHERE clause of your original query to get all rows for those items: 然后,您可以将其用作原始查询的`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');

Here is an SQL Fiddle example. 这是一个SQL Fiddle示例。

Thought I'd also include my Symfony2 / Doctrine solution, based on McAdam331's answer for SQL. 以为我还会包括我的Symfony2 / Doctrine解决方案,该解决方案基于McAdam331对SQL的回答。

I used a second query builder instance in the item repository for the subquery. 我在项目存储库中使用了第二个查询构建器实例作为子查询。 You just need to use different indexes than used in the main query builder, of course. 当然,您只需要使用与主查询构建器中使用的索引不同的索引即可。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM