SQL – searching for content within a comma separated list

[adsense id=”0514458240″ width=”468″ height=”60″]

I have seen many requests for information on how to filter in SQL where a value exists in a comma separated list of values which is stored in a single field.

My first observation is to look very closely at the design of your data model if this is possible. Let us imagine we have a table which contains the following:

Customer id attributes
1 a,b,c
2 a
3 b,c
4 c
5 a,b
6 b

The better design of the attributes would be to have a separate table with customer id and attribute as follows:

customer id attribute
1 a
1 b
1 c
2 a
3 b
3 c
4 c
5 a
5 b
6 b

By changing the design to this we can add an index on the attribute so that a search on attribute equal to a value will be efficiently performed in the database. A primary key should be added on customer id and attribute which makes sure we cannot add a second attribute of the same value for the same customer id. Also by creating a primary key on customer_id and attribute allows us to quickly return the attributes belonging to a customer_id.

In any case if the design cannot be changed we would need to write the SQL in the following way

  • Search for an exact search on an item i.e. only one attribute in the list
  • Search for attribute at the starting position in the list i.e. attribute,
  • Search for attribute at the end position in the list i.e. ,attribute
  • Search for attribute between 2 commas i.e. ,attribute,

Here is an example from a MySQL database:

mysql> create table customers ( customer_id int, attributes varchar(100));
Query OK, 0 rows affected (0.01 sec)

mysql> insert into customers(customer_id, attributes) values (1,'a,b,c'),(2,'a'),(3,'b,c'),(4,'c'),(5,'a,b'),(6,'b');
Query OK, 6 rows affected (0.00 sec)
Records: 6  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM customers WHERE attributes = 'a' OR attributes LIKE 'a,%' OR attributes LIKE '%,a,%' OR attributes LIKE '%,a';
+-------------+------------+
| customer_id | attributes |
+-------------+------------+
|           1 | a,b,c      |
|           2 | a          |
|           5 | a,b        |
+-------------+------------+
3 rows in set (0.00 sec)

mysql> SELECT * FROM customers WHERE attributes = 'b' OR attributes LIKE 'b,%' OR attributes LIKE '%,b,%' OR attributes LIKE '%,b';
+-------------+------------+
| customer_id | attributes |
+-------------+------------+
|           1 | a,b,c      |
|           3 | b,c        |
|           5 | a,b        |
|           6 | b          |
+-------------+------------+
4 rows in set (0.00 sec)