So, I have an array like this in my programming language:
x
$animalsToSearch = ['fox', 'cat', 'dog'];
And I have a MySQL database table like this:
id | value
----+----------------
1 | dog,elephant
2 | cat,dog
3 | spider,fox,cat
4 | cat
5 | dog,rabit
Unfortunately, I cannot change the table to be more relational (yet).
I want to pull out how many times an item in my array is present in the database value
column. Now, the obvious way to do this would be something like:
<?php
$count = [];
foreach (['fox', 'cat', 'dog'] as $animal) {
$count[$animal] = some_function_that_gets_the_data($animal);
}
But there might be dozens of animals to search for, and I don’t want to send a db request per animal. I have thought of the way below, and then using PHP to look at the values to see if the animal is present within… but it’s a bit hacky. Might there be a better way?
select
`value`
from
`animal`
where
find_in_set('fox', value)
or find_in_set('cat', value)
or find_in_set('dog', value);
ysth’s solution explain
‘d
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 PRIMARY <derived2> NULL ALL NULL NULL NULL NULL 2 100.00 Using temporary; Using filesort
1 PRIMARY animal NULL ALL NULL NULL NULL NULL 1,879,296 100.00 Using where; Using join buffer (Block Nested Loop)
2 DERIVED NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used
3 UNION NULL NULL NULL NULL NULL NULL NULL NULL NULL No tables used
Advertisement
Answer
Join against your list:
select animallist.animal, count(*) as times
from (
select 'fox' as animal union all select 'cat' union all select 'dog'
) animallist
join animal on find_in_set(animallist.animal, animal.value)
group by animallist.animal
You can try forcing it to only read through animal once, I don’t know if that will make it faster or slower:
select straight_join animallist.animal, count(*) as times
from animal on find_in_set(animallist.animal, animal.value)
join (
select 'fox' as animal union all select 'cat' union all select 'dog'
) animallist
group by animallist.animal