简体   繁体   中英

Querying a many-to-many relationship with added difficulty

Here is my problem: I have two tables connected trough a junction table. I'm using MySQL and PHP (Yii2) on an Apache server, but its just the SQL i need help with.

| Objects     |    ObjectHasTag    |   Tag    |
|---------------------------------------------|
| - id        |    -object_id      |   -id    |
| - name      |    -tag_id         |   -tag   |

I need to create a query that returns objects that is tagged with several tags, and my question is if this is doable with reasonable efficiency as a publicly accessible feature as a query.

Example: find all objects with tags 'tagone', 'tagtwo' and 'tagthree'.

I have one solution that works, and that is to have a 'tags'-column in the Objects-table, with all the tag-names divided by commas. This does not seem like a 'best practice'-kinda solution.

I really appreciate any help you guys can provide!

The SQL for this is relatively straightforward:

SELECT *
FROM Objects o
WHERE 3 = (
    SELECT COUNT(DISTINCT t.id)
    FROM ObjectHasTag ot
    JOIN Tag t ON t.id=ot.tag_id
    WHERE o.id = ot.object_id
      AND t.tag IN ('tag1', 'tag2', 'tag3')
)

The COUNT(DISTINCT t.id) joins ObjectHasTag to Tag , filters Tag on the list that you would like to search, and counts the number of distinct tags. In order for the object to be selected, all three items from the IN list must be present. If you know that ObjectHasTag cannot contain duplicate tagging, for example, because you have a unique index or a constraint on the table, you can replace COUNT(DISTINCT t.id) with COUNT(*) .

The o.id = ot.object_id condition "connects" the nested query to the object selected from Objects table.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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