I have a comma separated list of numbers in a MySQL entry 'id_user' like so:
127,130,150,12,4,7,8,9
What is the best way to find a number in this comma-separated list and (1) remove it with the comma if it's with other numbers or (2) just remove itself if the number is by itself like:
127
Then update the MySQL entry.
So if I wanted to remove 150 from the list, it would be updated in the MySQL as:
127,130,12,4,7,8,9
I want to avoid trying to remove the id '12' but end up removing the '12's in numbers like 127 or 512
Thank you!
Reading between the lines, it sounds to me like you are storing a list of foreign keys in a comma-separated string field to represent a many-to-many relationship. This is not a good idea.
What you should do instead is create a table to store the relations.
For example, lets say you have a table called users and you want to store friend relationships between them. What you are doing is something like this (N.B. I realised this is actually not a great example as I wrote the end but I'm sticking with it for now):
id | name | friends
------+--------+-----------
1 | Dave | 2,4
2 | Bob | 1
3 | Tom | 4
4 | Bill | 1,3
Whereas what it's much better to do is something like this:
users
id | name
------+--------
1 | Dave
2 | Bob
3 | Tom
4 | Bill
friends
id | user | friend
------+--------+----------
1 | 1 | 2
2 | 1 | 4
3 | 2 | 1
4 | 3 | 4
5 | 4 | 1
6 | 4 | 3
To select Dave's friends you can do
SELECT u.*
FROM friends f
JOIN users u ON u.id = f.friend
WHERE f.user = 1
...and to delete the relationship between Dave and Bob (what you want to do here), you can simply do
DELETE FROM friends
WHERE (
user = 1 AND friend = 2
) OR (
user = 2 AND friend = 1
)
Using PHP:
$array = explode(',', $string);
$pos = array_search('127', $array);
unset($array[$pos]);
$string = implode(',', $array);
Or using MySQL:
REPLACE(column, '127,', '')
REGEX_REPLACE(column, '127$', '')
Get UDF REGEX_REPLACE - https://launchpad.net/mysql-udf-regexp with ^127$
In PHP:
$string="," . $string . ",";
str_replace("127,", "", $string);
Or you could split the string:
$list=explode(",",$string);
$new="";
foreach($list as $item){
if($item!="127"){
$new.=$item.",";
}
$new=substr_replace($new ,"",-1);
That should work.
As pyrate suggests try this in MySQL
TRIM(BOTH ',' FROM REGEX_REPLACE(column, '127\,?', ''))
using the UDF
Hope this helps
Related
id | ozID | ozDa1 | ozDa2 | ozDa3
-----------------------------------------------
1 | 3,4 | Khar | Lorem | Emre
2 | 1,2 | Imson | Berkay | ade
3 | 2 | abc | Goksel | casc
4 | 5 | teq | Insanlik | fdsc
5 | 1,5,2 | asd | Oyle | asdas
6 | 2,1 | fav | Boyle | dsssa
7 | 3 | qwrewq | Filan | dcsd
I can write the content like:
$partNameWD->ozDa2; // Berkay
But the number at the end can be variable, like this: ozDa4.
At first I get the data from the ozID table, for example: 1,2
What does it mean 1,2?
It points to column numbers: ozDa1 and ozDa2
Access to this number is like this:
$ozColNo = explode(",", $partNameWD->ozID);
foreach (ozColNo as $ozColId) {
echo ozColId." - "; // 1 - 2
}
So what is my problem?
How do I get data from the column with these numbers? So, how can I print the data from one and the second
It has to be transformed: ozDa1 // Imson and ozDa2 // Berkay
Please can you tell me the method?
Thanks
I'm not 100% sure that I correctly understand the question, but you can get the mapping between "column number" and "column name" in information_schema.columns. So, if you are given a number, you can look up the name using:
select column_name
from information_schema.columns
where table_name = #table_name and table_schema = #table_schema and
ordinal_position = #op;
You can do a group of columns with a slightly more complicated approach (because I assume ordering is important)
select group_concat(c.column_name order by cols.ordering) as columns
from (select 1 as colpos, 1 as ordering union all
select 2, 2
) cols join
information_schema.columns c
on c.ordinal_position = cols.colpos
where table_name = #table_name and table_schema = #table_schema;
Try this.
$output= $partNameWD->{'ozDa' . $ozColId};
echo $output;
Check out the PHP.net site for this
http://php.net/manual/en/language.variables.variable.php
Caution
Further dereferencing a variable property that is an array has
different semantics between PHP 5 and PHP 7. The PHP 7.0 migration
guide includes further details on the types of expressions that have
changed, and how to place curly braces to avoid ambiguity.
I want to get result of joining multiple tables as one row and fetch multiple cuisine_name from t_cuisine table and get the cuisine_id in t_search.cuisineId column using php (CODEIGNITER) and joins
t_search table to get the cuisineId like this so that I can get the available cuisine names through the cuisineId.
t_search table
searchID|restaurant_name|cuisineId
1 | XYZ | 1,4,5
2 | KIH | 2
3 | GHY | 4,5
4 | UIO | 1,2,3
5 | RTY | 3,5
t_cuisine table
cuisineId|cuisine_name
1 | ABC
2 | CDE
3 | EFG
4 | GHZ
5 | HJL
in my Model i've used
$this->db->select('*');
$this->db->from('t_search');
$this->db->join('t_cuisine','t_cuisine.cuisineId = t_search.cuisineId');
which fetches data only based on single value in cuisineId in t_search.
$this->db->select('*');
$this->db->from('t_search');
$this->db->join('t_cuisine','t_cuisine.cuisineId IN(t_search.cuisineId)');
$this->db->where('t_cuisine.cuisineId', X);
Change X to the ID of the cuisine you are looking for
What you had previously (when your query worked based on a single value in cuisineId) was a one to many relationship. Joining like that worked well because each search had one cuisine.
This is a many to many relationship, and this table structure doesn't support it well. Instead of storing a delimited list in the cuisineId column of your t_search table, you need another table to represent the relationship between search and cuisine, like this:
t_search_cuisine table
searchID|cuisineId
1 | 1
1 | 4
1 | 5
2 | 2
3 | 4
3 | 5
4 | 1
4 | 2
4 | 3
5 | 3
5 | 5
Then you should be able to get all your data with one additional join.
$this->db->select('*');
$this->db->from('t_search');
$this->db->join('t_search_cuisine','t_search.searchID = t_search_cuisine.searchID');
$this->db->join('t_cuisine','t_search_cuisine.cuisineId = t_cuisine.cuisineId');
Based on the structure of your table, joining those table would be not easy. Perhaps you could do with two queries instead.
$this->db->select("cuisineId");
$this->where("searchID", $searchID);
$qry1 = $this->db->get("t_search");
$res1 = $qry1->row_array();
$qry1->free_result();
if ($res1) {
$this->db->select("*");
$this->db->where_in('cuisineId', $res1);
$qry2 = $this->db->get("t_cuisine");
$res2 = $qry2->result();
return ($res2) ? $res2 : false;
}
i am developing an small application which disease after asking about symptoms,,php + mysql
my table is
i have an array of symptoms, i want to get disease that match to array symptoms
$a= array('fever','pain');
$sql=mysql_query("select * from disease where `d_symptoms` like '$a'");
already tryed using join and in
echo $v=join(',',$a);
$sql=mysql_query("select * from disease where `d_id` in ($v)");
please help me
you need to have a new table called symptoms, which includes a foreign key of the disease id (d_id) in your current table and the symptom name (d_symptom). Then each row will have the name of the symptom and the id of the disease it is linked with. That way you will not have multiple values in the symptom field. You then call it be selecting all symptoms where id='d_id' to get the list of symptoms associated with that disease.
the query might be
$a= array('fever','pain');
$sql=mysql_query("SELECT d_name FROM disease, symptoms WHERE disease.d_id = symptoms.d_id AND d_symptom IN ($a)";);
or something..
The correct answer is to properly normalize your database. You shouldn't use comma separated values (as suggested in comments). I am sure you can find many articles teaching normalization, so I won't go into details here.
You need to separate the symptoms from the diseases.
Diseases table
id | d_name
---------------------
1 | Dengu
2 | Typhoid
3 | Cervical
Symtoms table
id | s_name
---------------------
1 | Fever
2 | Pain
3 | Vomit
4 | Abc
5 | Xyz
Diseases-Symptom table (this is an intersection)
id | d_id | s_id
---------------------------
1 | 1 | 1
2 | 1 | 2
3 | 1 | 3
2 | 2 | 3
3 | 2 | 2
1 | 2 | 4
2 | 3 | 2
3 | 1 | 5
This way you don't create duplicate symptoms and makes your data easier to use and present, for example
SELECT id, s_name FROM symptoms
will give you a list of all symptoms available.
SELECT diseases.id, diseases.d_name, symptoms.s_name
FROM diseases
JOIN diseases_symptoms ON d_id = diseases.id
JOIN symptoms ON symptoms.id = diseases_symptoms.s_id
WHERE diseases.id = 1;
will give you a result similar to:
id | d_name | s_name
---------------------------
1 | Dengu | Fever
2 | Dengu | Pain
3 | Dengu | Vomit
You may use a single FIND_IN_SET for each symtoms you are looking for:
$query = "SELECT * FROM disease WHERE 1=1 ";
foreach($a as $row)
$query += "AND FIND_IN_SET($row, d_symptoms)";
$sql=mysql_query($query);
Well, you shouldn't store multiple values in a single column, as a best practice rule.(I really would fix that).
But, maybe something like this would work if you want to continue the way you have it:
$query = "select * from disease where d_symptoms like " . $a[0];
for($i = 1; $i < count($a); i++){
$query = $query + " AND d_symptoms like " $a[$i];
}
$sql=mysql_query($query);
I have a table that contains some ingredients. Example:
id | title | ingredients
1 | ex1 | ketchup, chicken, salt, honey, mountain dew
2 | ex2 | beef, pepper, chili, honey, salt
And when the user searchs for the ingredients like:
ketchup, salt, honey
I generate a sql-query:
select * from recipes where(
(ingredients LIKE '%ketchup%')
AND (ingredients LIKE '%salt%')
AND (ingredients LIKE '%honey%')
And it returns all recipes containing these specific ingredients, and it works grey.
Now. I've added a range-slider, to pick how many of the entered ingredients that should match for the search to return anything. Lets say i chose that 2 ingredients should match at least, i want to make a PHP function that outputs a sql string that pairs everyone of the entered ingredients, but i simply don't have the mindset for it.
Example:
(ingredients LIKE '%ketchup%') AND (ingredients LIKE '%salt%')
OR
(ingredients LIKE '%ketchup%') AND (ingredients LIKE '%honey%')
OR
So on. So ketchup & salt pair, ketchup & honey pair, salt & honey pair.
And of course variable so theres no limit to the ingredients inputted. I've tried for hours but no success. Hope i've explained my self clearly & someone will be able to help or teach me something :-)
My php function that does the current string looks like this:
$c_soeg = "ketchup, whatever, whatever. etc";
$c_ing_arr = explode(",", $c_soeg);
$c_count_arr = count($c_ing_arr);
$i = 0;
$c_sql = "SELECT * FROM recipes WHERE (";
while($i < $c_count_arr){
$c_sql .= "(ingredients LIKE '%".trim($c_ing_arr[$i])."%')";
if($i != $c_count_arr-1){
$c_sql .= " AND ";
}
$i++;
}
$c_sql .= ")";
And the variable that contains the value of the range is named
$c_range;
Instead of AND and OR conditions count the met criteria. This example gives you all records where at least two ingredients match:
select * from recipes
where
case when ingredients like '%ketchup%' then 1 else 0 end
+
case when ingredients like '%salt%' then 1 else 0 end
+
case when ingredients like '%honey%' then 1 else 0 end
> = 2;
I think you should make 3 tables meaning
one for the title and another for the ingredients and one to connect them
recipy
id | title |
1 | ex1 |
3 | ex2 |
recipyingredients
recipyid | ingredientsid
1 | 1
1 | 2
1 | 3
1 | 4
1 | 5
2 | 1
2 | 6
2 | 7
ingredients
id | ingredients
1 | ketchup
2 | chicken
3 | salt
4 | honey
5 | mountain dew
6 | beef
7 | pepper
In that case one recipy can have many ingredients and viceversa
The database would be clearer and you would not have to use like % as much.
Also you do not have to write the same ingredients every time for a recipy
In my table 'users' there are 'friends' ,
Like this :
+----+------+---------+
| id | name | friends |
+----+------+---------+
| 1 | a | 0,1,2 |
| 2 | b | 0,1,3 |
| 3 | c | 0,1 |
+----+------+---------+
How do I use the explode function to get the friends id one by one (not 0,1,2) that are separated by a comma (,) ;
How do I select the id? (Example) :
$sql = Select id from users where id = (exploded)
if (mysql_num_rows($sql) > 0 ) {
$TPL->addbutton('Unfriend');
}else{
$TPL->addbutton('Add as Friend')
}
The solution here is actually a slight change in your database structure. I recommend you create a "many-to-many" relational table containing all of the users friends referenced by user.
+---------+-----------+
| user_id | firend_id |
+---------+-----------+
| 1 | 2 |
| 1 | 3 |
| 1 | 4 |
| 2 | 1 |
| 2 | 5 |
+---------+-----------+
If you are storing lists of values within one field then that is the first sign that your database design is not quite optimal. If you need to search for a numerical value, it'll always be better to place an index on that field to increase efficiency and make the database work for you and not the other way around :)
Then to find out if a user is a friend of someone, you'll query this table -
SELECT * FROM users_friends WHERE
`user_id` = CURRENT_USER AND `friend_id` = OTHER_USER
To get all the friends of a certain user you would do this -
SELECT * FROM users_friends WHERE `user_id` = CURRENT_USER
Just a simple example that will make you clear how to proceed:
// Obtain an array of single values from data like "1,2,3"...
$friends = explode(',', $row['friends']);
Then, back in your query:
// Obtain back data like "1,2,3" from an array of single values...
$frieldslist = implode(',', $friends);
$sql = "SELECT * FROM users WHERE id IN ('" . $frieldslist . "')";
to get an array of if ids from your string explode would be used like this
$my_array = explode("," , $friends);
but you'd probably be better using the mysql IN clause
$sql = "Select id from users where id in (".$row['friends'].")";
Just a quick idea. Change your database's table. It is certain that after a while many problems will arise.
You could have something like this.
id hasfriend
1 2
1 3
2 1 no need to be here (You have this already)
2 4
.....
You can do this by using indexes for uniqueness or programming. You may think of something better. Change your approach to the problem to something like this.