I have both side coma separated values like
$ing=1,2,3,4,5,6
and the database has a table with values
IDS 5,2,1,6,2,3,45 // in database
I know this is not a good practice but I had to do this to get the values in one query. i also have a separate table where the IDS are separate and corresponds to separate users like
user 1 IDS 2
user 3 IDS 65 etc
As of now I am using
$conditions[] = "CONCAT(',', `rcring`, ',') REGEXP ',($ing),'";
It gives me good results but it gives me the values in which either of the $ing exists i want only the tables which has atleast all the $ing
Can you help me please I tried my work and I cant get a proper solution anywhere . thankx .
//EDIT
i already have condition as an array
if($ser !=''){
$conditions[] = "rc_ser='$ser'";
}if($fridge == 1){
$ing="0|";
$ctch2fr='checked';
foreach($_SESSION['fridge'] as $item){
$ing=$ing.$item."|";}
$conditions[] = "CONCAT(',', `rcring`, ',') REGEXP ',($ing),'";
}
if (count($conditions) > 0) {
$sql= implode(' AND ', $conditions);
}
Like this as an condition in array and i am calling it like this in query
select * ,(select count(rcid) from recipe where ($sql)) as total from recipe where ($sql)
i tried the answers below bu it gives me 0 result always when i print the query it shows me like this
select *,(select count(rcid) from recipe where (CONCAT(',', `rcring`, ',') REGEXP ',(0),') ) as total from recipe where (CONCAT(',', `rcring`, ',') REGEXP ',(0),')
You seem to have a recipe table that contains comma separated list of ingredients:
And a list of given ingredients:
And you want to find recipes that could be prepared with the given ingredients (recipe ingredients is a subset of given ingredients). You need to write PHP code that builds the following query:
A rough outline of the PHP code based on your attempt (which you must convert to prepared statements):
Having said that, the correct solution is to normalize your data. Here is an outline of the structure:
The query:
And the result:
You need to split the
$ing
and check all its parts in the where-clause:As far as I can see, the condition You specified matches only when
rcring
contains $ing exactly as substring, e.g.rcring = "5,2,1,6,2,3,45"
wouldn't match$ing = "1,2,3,4,5,6"
from your example. To match here,rcring
should be stored as"1,2,3,4,5,45"
.Simple sorting wouldn't help here, as
$ing = "1,2,5,6"
wouldn't matchrcring = "1,2,3,4,5,6,45"
Simple way
Make
$conditions[]
contain a conjuntion of matches on distinct IDs, e.g.This will check what You want -- if
rcing
contains all IDs from$ing
However, this is quite slow for large (> 10^8 rows) tables. Such queries will work for O(n) time, checking all the rows in the table. For several gigabyte tables, it can take significantly more than a minute.
Optimization
Use Fulltext index searches. You need to store IDs separated by space, e.g.
1 2 3 4 5 45
, to allow index treat it as words. After indexing, the code may be rewritten like following:Now that will work quite fast, and would skip the rows that don't match at all!
BE CAREFUL!
Always use PHP::PDO and pass IDs as parameters!
Hackers may abuse your system by making SQL injections with passing something dangerous instead of IDs, for example:
123");DROP DATABASE TEST; COMMIT;//
This will turn$ings
into smth like"+1 +2 +123\");DROP DATABASE TEST; COMMIT;//"
and final query will look like
The right way is to PDO prepared statements howto and to always construct queries that way!