简体   繁体   中英

Getting all rows that have all of the entered values by querying the same column

I am trying to search for all users that have all of the entered tags but it is searching for them by looking in the same column.

SELECT u.*, t.* FROM user u
LEFT JOIN user_tags ut ON u.id = ut.user_id
LEFT JOIN tags t ON ut.tag_id = t.id
WHERE t.name = tag1 AND t.name = tag2

I am searching solely by tag and each user must have all of the entered tags, not just 1. I'm using PHP to add another AND clause based on the number of values entered so if there are 3 values, it will look like this:

SELECT u.*, t.* FROM user u
LEFT JOIN user_tags ut ON u.id = ut.user_id
LEFT JOIN tags t ON ut.tag_id = t.id
WHERE t.name = tag1 AND t.name = tag2 AND t.name = tag3

t.name only contains 1 tag name, not a comma-separated value. The tag names are linked to each user through the user_tags table where each user id can multiple tag ids like so:

user_id | tag_id
40      | 3
40      | 4
41      | 1
41      | 2
41      | 3

And my current query returns nothing because none of the columns have all 3 tag names.

You could do something like this. It will only return user id's that have all 3 tags.

SELECT    u.id
FROM      user u
          LEFT JOIN user_tags ut ON u.id = ut.user_id
          LEFT JOIN tags t ON ut.tag_id = t.id
GROUP BY  u.id
HAVING        SUM(CASE WHEN t.name = tag1 THEN 1 ELSE 0 END) > 0 
          AND SUM(CASE WHEN t.name = tag2 THEN 1 ELSE 0) > 0 
          AND SUM(CASE WHEN t.name = tag3 THEN 1 ELSE 0) > 0 

The simplest solution would be the following where 'count' would be the amount of tags you're querying for, so you'll only get the users who have all the specified tags.

SELECT u.*, count(*) as `count`
FROM `user` u 
    JOIN `user_tags` ut ON ut.`user_id`=u.`id`
    JOIN `tags` t ON t.`id`=ut.`tag_id`
WHERE t.`name`='tag1' OR t.`name`='tag2'
GROUP BY u.`id`
HAVING `count` = 2

lets use group_concat...

SELECT
    u.*
FROM
    user u
    JOIN user_tags ut ON ut.user_id = y.id
    JOIN tags t ON t.id = ut.tag_id
WHERE
-- limit only the tags you want
    t.name IN ( tag1, tag2, ... )
GROUP BY
    u.id
HAVING
    GROUP_CONCAT( t.name ORDER BY t.name SEPARATOR ',' ) = 'tag1,tag2,...'

note that, in the having section, tag order should be same in both sides of condition

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