2

I want to check in mysql if all given keys exists in set or not. like:

    $comma_separted_user_ids = "20,2,9,8,31,1";

    $query ="SELECT conversation_id FROM message 
             WHERE FIND_IN_SET($comma_separted_user_ids, user_ids) ";

    // data of user_ids = "1,2,8,9,20,31";

I want to check if all user id exist in user_ids column or not, user_ids are not properly ordered.

Please suggest a solution, thanks.

user007
  • 3,203
  • 13
  • 46
  • 77
  • correct would be `WHERE FIND_IN_SET(needle, haystack)` and you've got to use nice AND conditions. – VMai Aug 07 '14 at 16:08
  • Oh sorry that was writing mistake, I have corrected it. – user007 Aug 07 '14 at 16:10
  • 1
    Yet another example of difficult, highly inefficient query on coma-separated values (see also: [Is storing a delimited list in a database column really that bad?](http://stackoverflow.com/q/3653462/1446005)) – RandomSeed Aug 07 '14 at 16:14
  • are you trying to compare a comma separated list to a comma separated list?? – John Ruddell Aug 07 '14 at 16:15
  • yes, but they are not ordered. I want to check if all ids exist in column value. – user007 Aug 07 '14 at 16:17
  • @user007 im sorry but find_in_set does not compare two CSL (comma separated lists) together.. it compares one value with a comma separated list. – John Ruddell Aug 07 '14 at 16:39
  • @JohnRuddell OK, I create a relationship table, as per suggested in below answers. thanks for your time – user007 Aug 08 '14 at 00:29

4 Answers4

3

While it is technically feasible:

$query = 
  'SELECT conversation_id FROM message'
  . 'WHERE FIND_IN_SET(' 
  . str_replace(
      ',',
      ', user_ids) AND FIND_IN_SET('
      $comma_separted_user_ids
  )
  . ', user_ids)' ;

... you should never do this!

Instead, create a new table to model the many-to-many relationship that exists between your user and message entities (e.g. participant). This is basic normalisation.

Then the query becomes trivial and performant:

SELECT conversation_id FROM participant
WHERE user_id IN ($comma_separted_user_ids)
GROUP BY conversation_id
HAVING COUNT(user_id) = [number of items in $comma_separted_user_ids]
RandomSeed
  • 29,301
  • 6
  • 52
  • 87
  • Your solution is working good, but I will create a new relation table as per you guys suggested. thanks – user007 Aug 08 '14 at 00:30
1

Since you don't know the ordering, I don't see a way around FIND_IN_SET. Like others said, it'd be far better to normalise your table structure.

But in the interest of providing an answer to the question, you'll need to create a list of FIND_IN_SET operators.

// A list of IDs.
$comma_separated_user_ids = "20,2,9,8,31,1";

// The TRUE string will make sure that the array 
// always contains at least one item.
$where = array("TRUE");

// Iterate over the IDs and create strings such as
// "FIND_IN_SET(1, column_name_here)"
foreach(explode(",", $comma_separated_user_ids) as $id) {
    $where[] = "FIND_IN_SET($id, user_ids)";
}

Then it's a simple matter of joining the strings together:

// Join everything together with AND (&&).
// Since "0" is considered FALSE, this works.
$where = implode(" && ", $where);

// Query for rows.
$query ="SELECT conversation_id FROM message WHERE ($where) ";

Don't use this if you don't need to. It won't scale very well.

Community
  • 1
  • 1
RickN
  • 12,537
  • 4
  • 24
  • 28
1

You can do this:

SELECT conversation_id
FROM message 
WHERE FIND_IN_SET($comma_separted_user_ids, user_ids) > 0
GROUP BY conversation_id
HAVING count(distinct user_id) = 1 + (length($comma_separted_user_id) - length(replace($comma_separted_user_id, ',', '')))

The having clause is counting the number of elements in the comma separated list.

If you are creating the SQL, you should consider using a table to store the values instead of a list. A join approach can take advantage of indexes, which find_in_set() cannot.

Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786
-1

i guess you should write it like this :

$comma_separted_user_ids = "20,2,9,8,31,1";

    $query ="SELECT conversation_id FROM message 
             WHERE user_id IN ($comma_separted_user_ids) ";
may saghira
  • 564
  • 9
  • 16
  • I don't think this answers the question the user asked. (I'm just leaving a comment, I didn't downvote this answer.) The pattern in this answer is the normal pattern we'd see with a normalized data model. I believe that OP has a different problem: the "comma separated list" stored in a VARCHAR column, an all-too-familiar SQL anti-pattern. – spencer7593 Aug 07 '14 at 16:48