Array in where clause in mysql - php

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);

Related

SQL PHP query multiple tables data

Noob alert here!
I'm trying to display some data on my php page from two tables but I don't know how to do it
db_bandas TABLE
banda_id | banda_name
1 | Rolling Beatles
2 | Linkin Bizkit
db_albuns TABLE
album_id | album_name | banda_id | album_ano
1 | Music | 1 | 2000
2 | another | 2 | 2014
3 | good one | 1 | 2004
What I want to show on the page is like :
1 | Music | Rolling Beatles | 2000
2 | another | Linkin Bizkit | 2014
3 | good one | Rolling Beatles | 2004
I've tried the query like this
$sql = "SELECT db_albuns.album_nome AS album_nome, db_albuns.album_id AS album_id, db_albuns.album_ano AS album.ano, db_banda.banda_nome AS banda_nome FROM db_albuns,db_banda";
You can use Join to do it
$sql = "SELECT db_albuns.album_nome,
db_albuns.album_id, db_albuns.album_ano,
db_banda.banda_nome
FROM db_albuns join db_banda
on db_albuns.banda_id = db_banda.banda_id";
Your table name should be albums and columns name should be id, name, banda_id, ano. Your table name is albums, so I think there is no need to use prefix 'albums' for each column.
As well as another table name should be bandas and columns name should be id, name
And your query should be like this
$sql = "SELECT albums.id, albums.name, bandas.name, albums.ano
FROM albums JOIN bandas
on albums.banda_id = bandas.id";
There are a few different ways you can do this, but my go-to is a LEFT JOIN.
$sql = "SELECT album_id, album_name, banda_name, album_ano
FROM albuns LEFT JOIN bandas
USING (banda_id)
WHERE 1=1;
On a side not, prefixing your tables with db_ is a little confusing, because that's the name of a table, not a database.

SQL need to improve run speed

I am trying to select data from mysql by a date field in the database. (Users can enter start date and end date)
For each selected row between user selected dates, I need to select from the same table to produce a result.
Example:
$query = "SELECT * FROM table WHERE date BETWEEN $begindate AND $enddate"; //Select by date
$result = mysqli_query($dbc,$query);
while($row = mysqli_fetch_array($result)){
vardump($row); //user needs to see all data between date selection
$query = "SELECT * FROM table WHERE field = $row['field']";
// and then do calculations with the data
}
This runs very slowly and I can see why. How can I improve the run speed?
Edit:
The original purpose was to generate a sales report between dates. Now the user wants the report to produce another result. This result could only be produced by searching against the same table, and the rows that I need is not within the date selection.
Edit 2:
I do need to output the entire table between date selection. Each row will need to find ALL other rows where field = field, within or out side of the date selection.
Edit 3: Solved the problem. All the answers are helpful, though I think the chosen answer was most related to my question. However, I believe using join when working with two tables is the right way to go. For my problem, I actually just solved it by duplicating the table and run my search against the duplicated table. The chosen answer did not work for me because the second query selection is not a part of the first query selection. Hope this would help anyone looking at this post. Again, thanks for all the help!
Well, so if you are really looking for such a conditions in same table, I suggest you should use IN selector like following:
$query = "SELECT * FROM table
WHERE field IN
(SELECT DISTINCT field FROM table
WHERE
date BETWEEN $begindate AND $enddate)";
So final code will look some like following:
$query = "SELECT * FROM table
WHERE field IN
(SELECT DISTINCT field FROM table
WHERE
date BETWEEN $begindate AND $enddate)";
$result = mysqli_query($dbc,$query);
while($row = mysqli_fetch_array($result)){
// do calculations with the $row
}
I guess your table names arent TABLE:
just user inner join
$query = "SELECT *
FROM table1
JOIN table2
ON table1.field = table2.field
WHERE date BETWEEN $begindate AND $enddate
ORDER BY table1.field;"
Stop writing pseudo-SQL
SELECT * FROM is technically pseudo-SQL (a sql command which the interpreter has to modify before the command can be executed. It is best to get in a habit of specifying columns in the SELECT statement.
Use SQL joins
Joins are what makes relational databases so useful, and powerful. Learn them. Love them.
Your set of SQL queries, combined into a single query:
SELECT
table1.id as Aid, table1.name as Aname, table1.field as Afield,
table2.id as Bid, table2.name as Bname, table2.field
FROM table table1
LEFT JOIN table table2
ON table1.field = table2.field
WHERE table1.date BETWEEN $begindate AND $enddate
ORDER BY table1.id, table2.id
Your resulting print of the data should result in something which access each set of data akin to:
$previous_table1_id = 0;
while($row = mysqli_fetch_array($result)){
if ($row['Aid'] != $previous_table1_id) {
echo 'Table1: ' . $row['Aid'] . ' - ' . $row['Aname'] . ' - '. $row['Afield'] . "\n";
$previous_table1_id = $row['Aid'];
}
echo 'Table2: ' . $row['Bid'] . ' - ' . $row['Bname'];
}
Dealing with aggregated data
Data-aggregation (multiple matches for table1/table2 on field), is a complex subject, but important to get to know. For now, I'll leave you with this:
What follows is a simplified example of one of what aggregated data is, and one of the myriad approaches to working with it.
Contents of Table
id | name | field
--------------------
1 | foos | whoag
2 | doh | whoag
3 | rah | whoag
4 | fun | wat
5 | ish | wat
Result of query I gave you
Aid | Aname | Afield | Bid | Bname
----------------------------------
1 | foos | whoag | 1 | foos
1 | foos | whoag | 2 | doh
1 | foos | whoag | 3 | rah
2 | doh | whoag | 1 | foos
2 | doh | whoag | 2 | doh
2 | doh | whoag | 3 | rah
3 | rah | whoag | 1 | foos
3 | rah | whoag | 2 | doh
3 | rah | whoag | 3 | rah
4 | fun | wat | 4 | fun
4 | fun | wat | 5 | ish
5 | ish | wat | 4 | fun
5 | ish | wat | 5 | ish
GROUP BY example of shrinking result set
SELECT table1.id as Aid, table1.name as Aname
group_concat(table2.name) as field
FROM table table1
LEFT JOIN table table2
ON table1.field = table2.field
WHERE table1.date BETWEEN $begindate AND $enddate
ORDER BY table1.id, table2.id
GROUP BY Aid
Aid | Aname | field
----------------------------------
1 | foos | foos,doh,rah
2 | doh | foos,doh,rah
3 | rah | foos,doh,rah
4 | fun | fun, ish
5 | ish | fun, ish

DISTINCT * is not withdrawing the duplicity (MYSQL)

i already done everything to remove this duplicity on the database
On selecting a checkbox on the sectio "Bairros" i utilized as Array
for($m=0; $m<count($_POST["bairros"]); $m++){// LOOP 1
$pesquisar=($_POST["bairros"][$m]);
//Copy bairros(Array) and esporte (POST)
$query = "SELECT DISTINCT * FROM cadastro WHERE
(esporte1 = '".$_POST["esportes"]."' OR
esporte2 = '".$_POST["esportes"]."' OR
esporte3 = '".$_POST["esportes"]."' OR
esporte4 = '".$_POST["esportes"]."')
AND
(bairro1 = '".$pesquisar."' OR
bairro2 = '".$pesquisar."' OR
bairro3 = '".$pesquisar."' OR
bairro4 = '".$pesquisar."')
AND
ativarAparecer='sim' ORDER BY nomeCompleto ASC LIMIT 20";
$esporte= new consultar();
$esporte->executa($query);
//Loops
for($l=0; $l<$esporte->nrw; $l++){ //LOOP 2
echo $esporte->data["nomeCompleto"]."<br />";
$esporte->proximo();
} //close LOOP2
} //close LOOP1
Detail: this function object oriented, I believe that i'm doing something wrong at SQL or MYSQL, perhaps something is missing there.
SELECT DISTINCT *
Stop There. DISTINCT * can do what? Duplicate of what? it cant do that. Give it a field name to see unique values.
For example
SELECT DISTINCT nomeCompleto
Let's break this down. The DISTINCT clause will return unique sets based on the selected columns.
Let's say you have a table:
a | b | c
=========
1 | 2 | 3
1 | 1 | 3
1 | 2 | 4
Now if you SELECT DISTINCT a FROM table, you would get:
1
but if you SELECT DISTINCT a, b FROM table, you would get:
a | b
=====
1 | 2
1 | 1
That's because {1,2} is different from {1,1}, even though the a column is the same between those two sets.
Obviously, doing SELECT DISTINCT * FROM table would give you the original table because it uses all three columns as a "composition" of the unique set. If we amended the table to look like this:
a | b | c
=========
1 | 2 | 3
1 | 1 | 3
1 | 2 | 4
1 | 2 | 3
Then your result of SELECT DISTINCT * FROM table would give:
a | b | c
=========
1 | 2 | 3
1 | 1 | 3
1 | 2 | 4
because of the duplicate result set of {1, 2, 3}. However, since most tables have an auto-incrementing identifier as the primary key, there is almost always no difference between SELECT * and SELECT DISTINCT *.
Perhaps you're looking to GROUP BY a certain column?
How would I be using GROUP this in my script? Column that there are several equal records are this bairro, bairro2, bairro3, bairro4. Inside it is in numbers
bairro1 | bairro2 | bairro3 | bairro4
14 | 14 | 15 | 27
34 | 15 | 14 | 30
27 | 45 | 12 | 14

Exploding in php

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.

Show database entries separated by comma

I have one field in the backend, where I input IDs separated by comma - ID1, ID2, ID3....These are videos in fact. All ids are stored in the field product_videos in the database (as they are typed).
How can I echo these id's on the frontend so they all show for the product?
Storing comma separated data in one data field is a bad idea. It is a real pain to manipulate, so you should really consider revising your db structure.
You haven't shown your data structure, so I'll give a basic example and then explain how it can be improved. My example assumes product_videos is linked to particular users:
table: `users`
| user_id | user_name | product_videos |
|---------|-----------|----------------|
| 1 | User1 | 1,2,3,4,6,7 |
| 2 | User2 | 5 |
You would maybe run a query
SELECT `product_videos` FROM `users` WHERE `user_name` = 'User1'
This would give you one row, with a comma separate value - you would then need to use something like PHP's explode() to convert it into an array and then loop through that array. That is a very bad method (and it will only become harder as you try to do more advanced things).
Instead, it would be easier to use a link table. Imagine:
table: `users`
| user_id | user_name |
|---------|-----------|
| 1 | User1 |
| 2 | User2 |
table: `videos`
| video_id | user_id |
|-----------|---------|
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
| 5 | 2 |
| 6 | 1 |
| 7 | 1 |
In this example, each video is a separate row in a db table (and each video is linked to an existing user). Each row is readily able to be handled independently. This makes it really easy to handle extra data for each video, such as a title, runtime length, date of uploading, etc.
You would then need to run a JOIN query. e.g.
SELECT `videos`.`video_id` FROM `videos`
INNER JOIN `users` ON `users`.`user_id` = `videos`.`user_id`
WHERE `users`.`user_name` = 'User1'
In PHP, you would do something like:
$q = mysql_query("SELECT `videos`.`video_id` FROM `videos` INNER JOIN `users` ON `users`.`user_id` = `videos`.`user_id` WHERE `users`.`user_name` = 'User1'");
while ($row = mysql_fetch_assoc($q)) {
echo "VIDEO ID = " . $row["video_id"] . "<br/>";
}

Categories