I'm not an expert in PHP even though I've been working with some stuff, copying and pasting from here and there, well I want to ask something that I can not find and that I don't have the slightest idea on how to implement it.
For instance, at a table like this:
+------+-----+
|NAME |BIRTH|
+------+-----+
|John |1980 |
|Carl |1982 |
|Alice |1990 |
|June |1994 |
|Rob |1998 |
|Alice |1998 |
|John |2000 |
|Alice |2001 |
|Etc. | |
+------+-----+
I do different queries, like these below (and I could keep doing queries with any combination of years):
Select * from table where BIRTH between 1980 and 1990
Select * from table where BIRTH between 1980 and 2001
Select * from table where BIRTH between 1990 and 2001
So I will get 3 different tables, and from those tables I need to count the different contents,
for instance, from the table obtained with the query1 I need to obtain:
John = 1
Carl = 1
Alice = 1
from table of query2:
John = 2
Carl = 1
Alice = 3
June = 1
Rob =1
from table of query3:
Alice = 3
John = 1
Carl = 1
June = 1
Rob =1
And remember the big table has 700 records, so it could appear any new name, and I need to print out the result in the same way:
Alice = 3
John = 1
NewName = 1
June = 1
Rob =1
My final goal is do percentages in relation to the obtained table, and not to the total of registers.
You should do it in SQL, not in PHP :
select NAME, count(1)
from TABLE
where condition
group by NAME
This will produce the exact view you want. Names as first column, the count on the second.
Related
I have run into an issue selecting data from my MySQL database.
For example, I have a table with the following columns & tables:
Table name: farming
id | animal | amount | food
----------------------------
1 | Cow | 10 | Grass
12 | Sheep | 19 | Grass
23 | Lion | 1 | Everything
29 | Lamb | 3 | Grass
102| Pig | 8 | Everything
...
I want to get the amount from all the rows that match the food type of a selected id.
E.g. If I choose id: 102 then it would get the amount from ALL rows where the food = 'Everything'
SELECT amount FROM farming WHERE food = '".$_GET['food']."' **IS THE SAME TYPE AS IT IS IN** id = '1'"; // This should select 10, 19 and 3 from amount (as id = 1's foodtype is Grass, so it should select amount from all rows where foodtype = grass.
** is where I'm facing issues, I've tried various statements and can't seem to get it to work.
You could use group by clause which will sum up all value from amount column whre food = 'Grass'
SELECT SUM(amount) ammount FROM farming
WHERE food = (select food FROM farming where id = 102)
GROUP BY food
This should do the trick
select amount
from farming
where food = (
select food
from farming
where id = 1
)
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 got an database (phpmyadmin) in which I put users,
grid looks like this
+-----+---------+-----------------+----------------+
| id | user | categorie_bit | calender_week |
+-----+---------+-----------------+----------------+
| 1 | Kevin | 01 | 39 |
+-----+---------+-----------------+----------------+
the id and user is self explained. Categorie_bit stands for the current job he / she has to do like having a walk with the dog.
0 - no job
1 - job 1
10 - job 2
11 - both jobs
and the calender week shows the current calender week.
like this in php:
$date = new DateTime();
echo $date->format('W');
I got various users, each user has to do a job for this calenderweek for this instance 39.
The user is picked randomly from the database. (I used a PDO Wrapper)
$table = "users";
$columns = array("id", "firstname");
$orderBy = array('RAND()');
$result_set = $db->select($table,$columns, Null, Null, $orderBy, 1);
In the next step I give the user a "job".
Categorie_bit = 1.
The problem is now that I want to pick a user who did not have a "job" last calender week, so that all users are treated equally.
Edit:
How do I accomplish this for further usage, lets say user 1 had to work week 39 and user 2 for week 44 and so on...
My first idea is to change the random picker somehow.
Anyone knows how to accomplish this?
Just add a WHERE clause to your query checking if there's an entry last week for your user. I'm not familiar with your PDO wrapper but the resultant query should be:
SELECT u.id, u.firstname
FROM users u
WHERE (
SELECT COUNT(*)
FROM users u2
WHERE u.id = u2.id
AND u2.calendar_week = <?= $date->format('W') - 1 ?>
AND u2.categorie_bit > 0
) = 0
ORDER BY RAND()
LIMIT 1
UPDATE
To make sure each user wasn't assigned another job until every user had done a job at least once I would record the information differently. I would have two tables, one for users and one for the job they completed and the week they completed it on.
Users
+----+-------+
| id | user |
+----+-------+
| 1 | Kevin |
+----+-------+
Jobs
+----+--------+-----+------+
| id | userId | job | week |
+----+--------+-----+------+
| 1 | 1 | 01 | 39 |
| 2 | 2 | 10 | 39 |
| 3 | 6 | 01 | 40 |
| 4 | 8 | 10 | 40 |
+----+--------+-----+------+
Then you can use the following query:
SELECT u.id, u.user
FROM users u
LEFT JOIN jobs j ON u.id = j.userId
WHERE j.id IS NULL
ORDER BY RAND()
LIMIT 1
So now you only get users who haven't completed a job. Once everyone has completed a job and the query returns 0 results you just clear the jobs table and start afresh.
Okay so I am trying to make this form for teams. Something like:
Football Club Name | W-W-L-D-W (W=win, D=draw, L=lose)
The way I thought I will do this is by adding text. For example, there is this match between FC Apple - FC Banana. Banana wins 0-1. In the team's row from the teams table, the "form" column is modified, adding "-W". Another match for Banana, with Kiwi, which they lose. Again adding "-L" to the column. So now the column is "-W-L". Is this possible?
I've thought about making 5 colums, lastmatch, lastmatch2, ... lastmatch5. When a team wins, lastmatch5 is W. If lastmatch4 is null and the team loses, lastmatch4 will be L. If all lastmatch columns are filled, then make lastmatch1 = lastmatch2, 2=3, 3=4, 4=5 , 5 = null, and its filled by the result.
But this is very complicated... Thats why I thought about the first method.
Any other methods? What do you think?
First, to answer your question, you could just grab the current content, like W-W-L-D, from the column, add the recent outcome, like -W, and then update the column with the new string - W-W-L-D-W. But I don't suggest doing it this way. Storing individual records in a long string is probably not the best idea. Instead, create separate relational tables. This is just off the top of my head, but I would consider doing something more like this:
Table: Football_club
+========================+
| Id | Name |
|---------|--------------|
| 1 | Apple |
| 2 | Banana |
| 3 | Kiwi |
+========================+
//This table stores each Football club's basic info
Table: Matches
+================================================+
| Id | Date | Team1_id | Team2_id |
|-------|-----------|-------------|--------------|
| 1 |2014-05-14 | 1 | 2 |
| 2 |2014-05-15 | 1 | 3 |
| 3 |2014-05-16 | 2 | 3 |
+================================================+
//This table stores basic info about each match.
Table: Match_outcomes
+==================================+
| Id | Match_id | Winner_id |
|-------|--------------|-----------|
| 1 | 1 | 2 |
| 2 | 2 | NULL |
| 3 | 3 | 3 |
+==================================+
//This table stores match outcomes.
//A winner ID of NULL would mean it was a draw (you could also use 0 or -1 or some other value that is not a team id)
This way, you can always get the number of wins, losses, and draws for any team, or add matches and match outcomes pretty easily.
For example, to get number of wins for team $id:
(I haven't tested this, but I think it would work)
SELECT
COUNT(mo.id) AS wins
FROM match_outcomes mo
JOIN matches m ON m.id = mo.match_id
AND (m.team_id1 = $id OR m.team_id2 = $id)
WHERE mo.winner_id = $id
GROUP BY mo.winner_id
Update - Been messing around with this... here's a sample query to get all wins, losses, and draws for each team using the above DB:
SELECT
fc.name,
SUM(IF(mo.winner_id=fc.id, 1, 0)) AS wins,
SUM(IF(mo.winner_id!=fc.id, 1, 0)) AS losses,
SUM(IF(ISNULL(mo.winner_id), 1, 0)) AS draws
FROM match_outcomes mo
JOIN matches m ON m.id = mo.match_id
JOIN football_clubs fc ON fc.id = m.team1_id
OR fc.id = m.team2_id
GROUP BY fc.name
See this SQL Fiddle
This is just a rough idea - hopefully it's helpful!
Name Hobby
John | Fishing,Traveling
Mary | Reading,
Tom | Music,
Kate | Cooking,Reading
George | Traveling,
Peter | Fishing,
Lisa | Cooking,
I want to select this table
Hobby Count
Fishing | 2
Traveling | 2
Reading | 2
Music | 1
Cooking | 2
How can I do that?
Use your table properly instead of cramming multiple hobby values into a single column. You should have:
John | Fishing
John | Traveling
Mary | Reading
Tom | Music
Kate | Cooking
Kate | Reading
George | Traveling
Peter | Fishing
Lisa | Cooking
Then you can do:
select hobby
, count(*) count
from tablename
group by hobby
order by hobby
I would do it like #Wes
or if its not possible i'd do it in PHP
$result = array();
$sql = 'SELECT Hobby, count(*) as cnt FROM youttable GROUP BY Hobby';
foreach ($conn->query($sql) as $row) {
foreach(explode(',',$row['Hobby']) as $hobby) {
$result[$hobby] += $row['cnt'];
}
}
Generally what you would do is have a separate table for hobbies.
So your first table would be consisted of: nameID, name.
And your second table would consist of: hobbyID, nameID, description.
Once you have it set up like that, you use nameID to link the two tables together.
SELECT * FROM nameTable, hobbyTable WHERE nameTable.nameID = hobbyTable.nameID
And when you have that you can use count() on the hobbyTable to get the quantities.
SELECT Hobby, Count(*) FROM myTable ORDER BY Hobby GROUP BY Hobby