Obviously storing a string of numbers in a comma-separated list is wrong from a database normalization perspective. I saw that others tried to close the question as a duplicate of "Is storing a delimited list in a database column really that bad?" but that's not a duplicate because it rejects the OP's question instead of answering it.
Let's discuss options for solving this.
The first choice would be to normalize it properly. Create a child table and store a reference to the id
in the table you show, plus one site value per row.
| id | site |
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 1 |
| 2 | 2 |
...
Then you can do groupwise counts, or at least do a GROUP_CONCAT() in sorted order so you can compare to your criteria.
SELECT id, GROUP_CONCAT(site ORDER BY site) AS sites
FROM MyTable GROUP BY id
HAVING sites = '1,2,3'
If you can't change the organization of data, it would help a lot if you could fix the strings so that the numbers were always in ascending order. But you probably can't do that (or don't want to try).
Another option is to compare one value at a time using the FIND_IN_SET() hack that some people use to search comma-separated strings. It's not intended for this purpose, it's a function to work with MySQL's SET data type, but it works on strings too, so people who are stuck with comma-separated strings of numbers use it.
SELECT ...
FROM YourTable
WHERE FIND_IN_SET('1', sites)
AND FIND_IN_SET('2', sites)
AND FIND_IN_SET('3', sites)
You'd need as many terms as the numbers you're searching for. But you also need to make sure the set doesn't contain more numbers.
AND LENGTH(sites) - LENGTH(REPLACE(sites, ',', '')) + 1 = ?
In this expression, ?
is the number of elements we're looking for: 3.
This type of solution may work, but it can't be optimized. It will always do a table-scan, so it'll get slower and slower the larger your table gets.