简体   繁体   中英

Using in from a group_concat

So I have two tables, one holding all users, and the other holding users with their corresponding groups. What I'm trying to do is to get all the user ids in the second table to get all the information I need from the first table. My explanation is a bit messy, but I think the code below should be clear enough

SELECT
    *
FROM
    USER
WHERE
    id IN (
        SELECT
            group_concat(userid)
        FROM
            user_membership
        WHERE
            groupid = 45
    );

However, what returns is the empty set. When I replace the 'in' with an '=' it returns a single entry (as expected). What's wrong with my syntax? Thanks.

You don't need group_concat() here as it concatenates every userid into a string column and you need to compare each user.id with a single user_membership.userid value, not an entire set. It's an overkill to perform that operation.

Simple select would suffice. However, it will probably be more efficient to rewrite your query using EXISTS :

select *
from user u
where exists (
  select 1
  from user_membership um
  where u.id = um.userid
    and groupid = 45
  )

If you really insist on the IN clause then correct query would look:

select *
from user
where id in (
  select userid
  from user_membership
  where groupid = 45
  )

You can use FIND_IN_SET

SELECT
 *
FROM USER
WHERE
FIND_IN_SET(id ,( SELECT group_concat(userid) FROM user_membership WHERE groupid = 45 ))

You can use INNER JOIN

SELECT
    U.*
FROM USER U 
INNER JOIN user_membership UM ON UM.userid = U.id 
WHERE UM.groupid = 45

Or you can use EXISTS like Kamil G mentioned in his answer.

id is a number, group_concat returns a string, containing all the ids separated by comma. I do not know the cause of the behavior you experienced, but I believe you could resolve the problem like this:

SELECT
    *
FROM
    USER
WHERE
    (
        SELECT
            CONCAT(',', CONCAT(group_concat(userid), ','))
        FROM
            user_membership
        WHERE
            groupid = 45
    ) LIKE CONCAT(',', CONCAT(id, ','));

Explanation: we write comma at the start and end of the inner result to allow LIKE to have a general operator. But your query can be optimized if you use EXISTS :

SELECT
    *
FROM
    USER
WHERE
    EXISTS (
        SELECT
            1
        FROM
            user_membership
        WHERE
            user_membership.groupid = 45 and user_membership.userid = USER.id
    );

Looks much more like a job for a join

SELECT
    *
FROM
    USER u inner join 
     user_membership m on m.userid = u.id
WHERE
         m.groupid = 45
   ;

That should run much faster as the query can more easily use the index

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