I have 3 tables the subject, student, and relation
The following are sample data
students table
id name
1 John
2 Doe
3 Jane
subject table
id subject
1 Math
2 Science
3 English
relation table
id student_id subject_id
1 1 1
2 1 3
3 2 1
4 1 2
in this case sudent with id=1 has 3 subjects. How can I get result like this?
student name is John
subjects are:
Math
Science
English
I already get the values for student, what I'm trying to do is get his subject to be shown by user.
I'm totally confused using join tables. I'm a newbie in php and I start learning this last week. I'm getting an error on my code. Please help.
My Cuurent code is this:
<?php
//mysql connection
$query = "
SELECT *,* FROM relation, subject
on subject_id = id
WHERE student_id = $student_id
";
$result = mysql_query($query);
?>
Student name is <?php echo $name ?><br />
Subjects are:<br />
<?php
while($row = mysql_fetch_array($result)) {
echo $row["subject"];
}
?>
Start by making sure your query is right. I think this is what you're looking for:
SELECT subjects.*
FROM subjects,
INNER JOIN relations ON relations.subject_id = subjects.id
WHERE relations.student_id = $student_id
It might pay to check it in a mysql client first (e.g., phpMyAdmin). You'll notice in the SELECT part I only have subjects.* because that is all you need.
I actually ask an interview question to weed out people who don't have basic SQL knowledge but claim it on their resume that this is a direct implementation of. It can lead to a good conversation about database design, normalization, de-normalization etc.
What I'd want to see is the basic join syntax that goes hand in hand with the relationship table you've created.
"Select subject from subjects inner join relations on relations.subject_id = subjects.id where relations.student_id = ?".
Taking it the next step you get to
"Select subject from subjects inner join relations on relations.subject_id = subjects.id inner join students on relations.student_id = students.student_id where students.name = ?".
allowing you to query without pre-fetching the student id if you don't want to expose your internal database keys to the external user.
The question mark is for variable binding, its rare that its a reasonable practice to not escape inputs for database interactions. Variable binding for queries is an easy way to get good coverage on that issue.
I love asking this design problem as an interview question because it can quickly lead to discussions about SQL injection, how to sanitize web form input, and general best practices in data management, web application development and database design.
There's the GROUP_CONCAT() aggregate function for this situation:
SELECT students.id, students.name, GROUP_CONCAT(subject.subject) AS subjects
FROM students
LEFT JOIN relation ON students.id = relation.student_id
LEFT JOIN subject ON relation.subject_id = subject.id
GROUP BY students.id
ORDER BY students.name
which will return data like this:
+-------------+---------------+------------------------+
| students.id | students.name | subject.name |
+-------------+---------------+------------------------+
| 1 | John | Math, English, Science |
| 2 | Doe | Math |
| 3 | Jane | NULL |
+-------------+---------------+------------------------+
You can do this without the grouping, in which case you'll get one row for every id/student name/subject name, and then you can use a simple state machine like in OMG Ponies' answer for the display portion.
<?php
//mysql connection
function query($query){
global $conn;
$qu=mysqli_query($conn,$query);
return $qu;
}
$query1 =query("
SELECT * FROM student
WHERE student_id = $student_id
");
$query2=query("SELECT * FROM relation, subject
WHERE relation.student_id = $student_id
AND subject.id=relation.subject_id
");
$name=mysqli_fetch_assoc($query1);
?>
Student name is <?=$name['name']?><br />
Subjects are:<br />
<?php
while($row = mysql_fetch_array($query2)) {
$rew[]=$row['subject'];//For store subject
echo $row["subject"];
}
$subject=join(",",$rew);//Get the stored subject from array
?>
Maybe can help you ?
The simple way to do this, is to query all students:
SELECT * FROM `students`;
and then loop the resultset in php, now for each of the rows you have to make another query to get students subjects:
SELECT * FROM `subject` WHERE `id` IN (SELECT subject_id FROM relation WHERE student_id={$student_row['id']})
assuming $student_row is the name you choose for assigning fetched record.
Now, you do a nested-loop to fetch this query, and print students' subjects.
Related
I stumbled upon a query that I have never done until now.
Before asking the question I looked for if another user had had the same need as me but nothing.
My goal is very simple:
having two tables:
collaboratori (collaborators)
invite (invitations)
I have to count how many invitations the collaborators have made.
table structure of collaboratori:
ID_Collaboratori | cod_manager
37 4675
150 6675
3 6575
table structure of inviti:
invite_id | invite_code_manager
37 6675
39 6575
40 4675
41 6675
if I execute the join obviously I access the two tables in this way:
$q_stats_prod_manager = $connessione->prepare("
SELECT * FROM invite
LEFT JOIN collaboratori
ON collaboratori.cod_manager = invite.invite_code_manager ");
$q_stats_prod_manager->execute();
$r_stats_prod_manager = $q_stats_prod_manager->get_result();
my need lies in showing in a table:
show me for each manager who has his cod_manager inside the inviti table, the number of times he sent them.
Name Surname Manager 1 | Number of invite: 200
Name Surname Manager 2 | Number of invite: 50
Name Surname Manager 3 | Number of invite: 10
not limiting myself to just one counter but also being able to access other table values like any join
I take the liberty of putting the answer that was partially written by another user, adding a detail and explanation for future users. The resolution query for this case is the same:
$q_stats_prod_manager = $connessione->prepare("
SELECT count(invite.invite_id)
/*name of what you want to call the result you will see in the while*/
AS result_count, /*you can call this value whatever you want*/
/*Start | Values of the tables you are interested in selecting*/
collaboratori.nome,
collaboratori.data_registrazione,
invite.invite_code_manager
/*End | Values of the tables you are interested in selecting*/
FROM collaboratori
LEFT JOIN invite
ON invite.invite_code_manager = collaboratori.cod_manager group by invite.invite_code_manager
");
$q_stats_prod_manager->execute();
$r_stats_prod_manager = $q_stats_prod_manager->get_result();
$count_invite_manager=mysqli_fetch_array($r_stats_prod_manager);
$number_of_invite_manager = $count_invite_manager[0];
Select the id of the table you want to count
Give a name you wish you want to name the counted result
Select the values of the tables on which you will perform the join you want to view
Join the tables
Show the result with while
Code while:
<?php while($rowstatspm = mysqli_fetch_assoc($r_stats_prod_manager)){ ?>
<!-- this is the fancy name you associated with your query when you wrote: AS nameofwhatyouwant -->
<?php echo $rowstatspm['result_count'] ;?>
<?php } ?>
You seem to want aggregation. I assume you want all rows for collaboratori, so that should be the first table for the LEFT JOIN:
SELECT c.cod_manager, COUNT(i.invite_code_manager)
FROM collaboratori c LEFT JOIN
invite i
ON c.cod_manager = i.invite_code_manager
GROUP BY c.cod_manager;
Your question doesn't describe where the name comes from. But those fields should be in both the SELECT and GROUP BY.
SELECT count(invite.invite_id),collaboratori.name FROM collaboratori
LEFT JOIN invite
ON invite.invite_code_manager = collaboratori.cod_manager group by invite.invite_code_manager
I have table called skills in which different skills are stored for that particular user in % so basically i want to select highest skills for that user from skills table and want to echo it in while loop for every user
user | skills |
userID | PHP |
userName | C++ |
<?php
$sql= "(SELECT *,max(skills) as higherPercentage
FROM skill LEFT JOIN user ON skill.userID=user.userID ORDER BY signup_date DESC ) ";
$res = mysql_query($sql) or die(mysql_error());
while ($row = mysql_fetch_assoc($res)) {
?>
So If the user has Highest vale 99 compare to all the skills then it should be selected for him
Store values in like 1,0.5,6 not like 100%,10%
and then use
SELECT MAX(column_name) FROM table_name group by (user)
I would like to set up a voting system to buddy up a fair few people in a table if they select each other. An example table would be
---------------------
User | vote | Buddy |
---------------------
A |C |no |
B |C |C |
C |B |B |
D |G |no |
E |no |no |
F |G |no |
G |A |no |
---------------------
The votes are cast by a radio button form, where users have a choice of anyone but themselves. These choices then update the vote column with the username of the person they have voted for. In this instance user E has not voted, and so has the default 'no'. I have built up to this point.
Next, I would like there to be a comparison of the user and vote column. If one user has voted for another, and they in turn have voted for them, I would like their username added to the users buddy column. In this instance, B would like to buddy with C and C would like to buddy with B, so there is a match and each others users names have been added to the buddy column. Although a couple of people voted for G, G voted for A, and so no further additions to the buddy column need to be added in this instance, so remain at the deafult 'no'.
I've guessed that a way to do it may be to cycle through the user column, select which one they have voted for and compare that choice with the choice of the user they voted for. However, putting this into code has proven very difficult, and so far I've only managed this code below. I tried to narrow it down to only users who have been voted for, before cycling through to save time. I'm not that keen on the 2 selections, I guess that one can go, and I know it won't be ideal to SELECT * for this basic function, but it's there whilst I work on it while the table is in trial mode in case I think of another column that may help.
$sql = <<<SQL
SELECT *
FROM `table`
SQL;
if(!$result = $db->query($sql)) {
die('There was an error running the query [' . $db->error . ']');
}
if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
$vote = $row['vote'];
$sql2 = <<<SQL
SELECT *
FROM `players`
WHERE user = '$vote';
SQL;
if(!$res = $db->query($sql2)) {
die('There was an error running the query [' . $db->error . ']');
}
if ($res->num_rows > 0) {
while($line = $res->fetch_assoc()) {
$user = $line['user'];
echo $name;
}
}
}
}
Any ideas, answers or tutorials that may help will be much appreciated - let me know if you need any more info. Thanks, Toastie
You would just do this with an update:
update example e join
example e2
on e.user = e2.vote and e2.user = e.vote
set e.buddy = e.vote;
I have these tables:
table 1 : attendance
-------------------------------
ID | DATE | EMPLOYEE_ID |
-------------------------------
1 2013-09-10 1
2 2013-09-10 2
3 2013-09-10 3
-------------------------------
table 2: employee
---------------
ID | NAME |
---------------
1 Smith
2 John
3 Mark
4 Kyle
5 Susan
6 Jim
---------------
My actual code to show employee option.
while($row=mysql_fetch_array($query)){
echo "<option value='$row[employee_id]'>$row[first_name] $row[last_name]</option>";
}
?>
How can i show the list of employee that not registered in table 1?
The condition is if an employee already registered in table 1, they won't appear on the option.
I want to show the list in <option>'s of <select> element. So it will return: kyle, susan, jim.
Please tell me the correct query or if there is any better option, it'll be good too. Please give some solution and explain. Thank you very much
UPDATE / EDIT:
it also based on current date, if in table 1 have no latest date e.g. today it's 2013-09-15. It will show all of employee.
You can do this with a left join and then checking for no matches:
select e.*
from employee e left outer join
attendance a
on e.id = a.employee_id
where a.employee_id is null;
This is probably the most efficient option in MySQL.
EDIT:
To include a particular date, add the condition to the on clause:
select e.*
from employee e left outer join
attendance a
on e.id = a.employee_id and a.date = date('2013-09-20')
where a.employee_id is null;
If I understood correctly this should work, get all employees whose ID is not in the attendance table.
SELECT * FROM employee WHERE employee.ID NOT IN
(SELECT EMPLOYEE_ID FROM attendance)
I have two tables: Team and player. Team player id's table. When I run the tool url, url and name of the player Starring table, I want to take.
player table
player
p_id p_name p_url
1 Iker Casillas iker-casillas
2 Mesut Ozil mesut-ozil
3 Xavi xavi
4 Victor Valdés victor-valdes
team
t_id t_name t_url player
1 FC Barcelona fc-barcelona 3,4
2 Real Madrid C.F. real-madrid-cf 1,2
team url is running, players want to print the name and url.but I can not get the result. where I make mistakes.
include('confing.php');
$t_url = $_GET["t_url"];
$sql = mysql_query("select player.p_name,player.p_url from player,team where player.t_id = team.t_name and team.t_url='.$t_url.'");
while($write = mysql_fetch_assoc($sql)) {
echo ''.$write['t_name'].'';
}
you need to use FIND_IN_SET
SELECT b.*
FROM team a
INNER JOIN player b
ON FIND_IN_SET(b.p_ID, a.player) <> 0
WHERE a.t_url = 'valueHere'
SQLFiddle Demo
one more thing, your code is vulnerable with SQL Injection, please read the article below to prevent from it
How can I prevent SQL injection in PHP?