The Mysql INNER JOIN fetch same data repeatly - php

I try to design a web that keep track the match history of students.
tablegame has 4 column: player 1, player2 ,player 3 and player4. All of them are represented as ids in tablegame.(each game has a maximum of 4 player)
The column player1 player2 always store the IDs who win this game, and column player 3 player4 always store IDs who lose this game.
Tableplayer store basic information about the student.
However, as I fetch associated array from the $AimStudentHistoryWin. Data get repeatly fetched.
THE web actually shows me this:
================
GAMEID 15
================
GAMEID 16
================
GAMEID 15
================
GAMEID 16
================
GAMEID: 15
================
GAMEID 16
BUT I expect the web to only show me
================ GAMEID 15
================ GAMEID 16
How could I Fix that?
echo "<br><br> <center><h2>match history:</h2> <br>";
$Aimstudenthistorywin=$conn ->query( "SELECT tablegame.*,tableplayer.Name FROM tablegame INNER JOIN tableplayer ON tablegame.player1 ='$studentid' OR tablegame.player2 ='$studentid'");
$Aimstudenthistoryloss=$conn ->query("SELECT tablegame.*,tableplayer.Name FROM tablegame INNER JOIN tableplayer ON tablegame.player3 ='$studentid'OR tablegame.player4 ='$studentid'" );
$Num=0;
While($row2= $Aimstudenthistorywin ->fetch_assoc()){
echo "<br>================<br><i style ='color:blue;'><h3>WIN</h3></i>";
echo "<br>Game".$Num;
$Num++;
echo "<br>".$row2['GameID'].":<br>".$row2['Name'];
}while($row2 = $Aimstudenthistoryloss -> fetch_assoc()){
echo "<br>================<br><i style ='color:red;'><h3>Lose</h3></i>";
echo "<br>Game".$Num;
$Num++;
echo "<h3>StudentName:".$TempStudentArray[$row2['player1']]."</h3><br>Game Date:".$row2['Date']."<br><br>"."----------------<br>Player1:".$TempStudentArray[$row2['player1']]."|||||||"."Player2:".$TempStudentArray[$row2['player2']]."<br><br>vs<br><br>Player3:".$TempStudentArray[$row2['player3']]."|||||||| Player4".$TempStudentArray[$row2['player4']]."<br>-------" ;
}
echo"</center>"

Ok it is solved.
instead of using
"SELECT tablegame.*,tableplayer.Name FROM tablegame INNER JOIN tableplayer ON tablegame.player1 ='$studentid' OR tablegame.player2 ='$studentid'");
We can just add more conditions into this. Eventhough I don't know why it works but it works
"SELECT tablegame.*,tableplayer.Name FROM tablegame INNER JOIN tableplayer ON (tableplayer.StudentID = tablegame.player1 OR tableplayer.StudentID = tablegame.player2) AND (tablegame.player1 ='$studentid' OR tablegame.player2 ='$studentid')");

Your duplicates come from your join's ON clause, which basically acts as if it was a WHERE clause.
To fix it, you can properly JOIN both tables (using a column of each), and then selecting only those involving your specific student (in the WHERE clause):
SELECT tablegame.*,tableplayer.Name
FROM tablegame
INNER JOIN tableplayer
ON tablegame.player1 = tableplayer.StudentID
OR tablegame.player2 = tableplayer.StudentID
WHERE tableplayer.StudentID = [the id of your student]
This request will avoid duplicates (assuming a student can't be player 1 and 2 at the same time)
And while at it, I would suggest always using prepared statements, to avoid potential SQL injections.

Related

Count from selection and access both tables with joins

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

Echo data from two different mysql tables using php

I'm trying to display data from two different mysql tables on my website using php.
My aim is to display a match schedule with information from two tables. The first one includes all the teams plus their ID, the second includes all details on the games. I now want to "replace" the "home_id" and "away_id" fields with the respective team names from the first table.
The tables look as follows:
table "teams"
id name
-----------
1 Team 1
2 Team 2
3 Team 3
4 Team 4
...
table "matchschedule"
id home_id away_id goals_home goals_away date
1 1 2 0 2 2016-05-05
2 3 4 2 1 2016-05-06
...
With the following query I'm getting the required data within phpmyadmin:
SELECT
date, home.name, sp.goals_home, away.name, sp.goals_away
FROM
matchschedule sp
INNER JOIN
teams home on sp.home = home.id
LEFT JOIN
teams away on sp.away = away.id
However, when I implement this query into my website and add the code below to display the data the fields "home.name" and "away.name" are always empty. What do I need to change in order to get the team names displayed?
while($row = mysql_fetch_array($query)) {
?>
<table border=1>
<tr>
<?php
echo "<td>".$row['date']."</td>";
echo "<td>".$row['home.name']."</td>";
echo "<td>".$row['goals_home']."</td>";
echo "<td>".$row['away.name']."</td>";
echo "<td>".$row['goals_away']."</td>";
?>
</tr>
</table>
Final result (with missing info for both team names):
2016-05-05 [] 0 [] 2
2016-05-06 [] 2 [] 1
The issue is that when in query you request home.name mysql return to php column with title name and you can not reach that column using home.name anymore. And same for away.name.
That's why you need to set proper name for returned columns.
Change your query to:
SELECT
date, home.name home_name, sp.goals_home, away.name away_name, sp.goals_away
FROM
matchschedule sp
INNER JOIN
teams home on sp.home = home.id
LEFT JOIN
teams away on sp.away = away.id
and call those columns in php like:
echo "<td>".$row['date']."</td>";
echo "<td>".$row['home_name']."</td>";
echo "<td>".$row['goals_home']."</td>";
echo "<td>".$row['away_name']."</td>";
echo "<td>".$row['goals_away']."</td>";
Based on your table strcture, you should do the following :
SELECT
date, home.name AS homeName, sp.goals_home, away.name AS awayName, sp.goals_away
FROM
matchschedule sp
INNER JOIN
teams home on sp.home_id = home.id
LEFT JOIN
teams away on sp.away_id = away.id
So basically replace sp.home by sp.home_id and sp.away by sp.away_id and change the fields name as you have the same fields name in your tables.

MySQL selection using LEFT JOIN

I am trying to join two tables and select from 'railstp'. I have simplified the tables.
Table 'railstp' looks like below
count startdate startlocation atoc
1 2013-09-28 lester a
2 2013-09-28 nottm a
3 2013-09-20 lester a
4 2013-09-28 birm a
Table 'location' looks like below
count startlocation goodlocation
1 lester Leicester
2 nottm Nottingham
I am trying to get the 'proper' (goodlocation) description from the table 'location' to replace the abbreviated description (startlocation) and also SELECT all the locations with a startdate of 2013-09-28. If there is not a 'proper' description it would be great if I just show the abbreviated description
So the result I am looking to achieve is
2013-09-28 Leicester a
2013-09-28 Nottingham a
2013-09-28 birm a
My code is as below:-
require('connect_db.php');
mysqli_select_db($mysql_link,"Timetable");
function show_records($mysql_link)
{
$q="SELECT railstp.startdate,railstp.startlocation,railstp.atoc,location.startlocation,location.goodlocation
FROM railstp
LEFT JOIN location
ON railstp.startlocation=location.startlocation
WHERE railstp.startdate='2013-09-28'
ORDER BY startdate";
$r=mysqli_query($mysql_link,$q);
if ($r)
{
echo "<Table id='customers'>
<tr>
<th>From</th>
<th>Departing</th>
<th>ATOC</th>
</tr>";
while ($row=mysqli_fetch_array($r,MYSQLI_ASSOC))
{
echo "<tr>";
echo "<td>".$row['startdate']."</td>";
echo "<td>".$row['startlocation']."</td>";
echo "<td>".$row['atoc']."</td>";
echo "</tr>";
}
echo "</Table>";
}
else {echo '<p>'.mysqli_error($mysql_link).'</p>' ;}
}
show_records($mysql_link);
mysqli_close($mysql_link);
The selection does not show the 'Proper' (goodlocation) description - ie it should show Nottingham instead of nottm and Leicester instead of lester
Thank you for your help
You can use the SQL-function COALESCE() for that.
This function uses the first non-null value in its arguments.
SELECT railstp.startdate,
COALESCE(location.goodlocation, railstp.startlocation) as startloc,
railstp.atoc
FROM railstp
LEFT JOIN location
ON railstp.startlocation=location.startlocation
WHERE railstp.startdate='2013-09-28'
ORDER BY startdate
So here, if location.goodlocation is NULL, railstp.startlocation is used.
See SQL-fiddle.
UPDATE
If you want to add an endlocation, you can join the location table again.
I'll point out that, in order to make things a bit easier, I've added table aliases to distinguish between the different tables.
SELECT r.startdate,
COALESCE(l1.goodlocation, r.startlocation) as startloc,
COALESCE(l2.goodlocation, r.endlocation) as endloc,
r.atoc
FROM railstp r
LEFT JOIN location l1
ON r.startlocation = l1.startlocation
LEFT JOIN location l2
ON r.endlocation = l2.startlocation
WHERE r.startdate='2013-09-28'
ORDER BY r.startdate
This, off course, if the location table is used for both start and end locations.
You have two columns with the same name in your query. There is no way to tell which one you want in the php code, so the first is chosen. Use as to rename one of them:
SELECT rs.startdate, rs.startlocation as shortstartlocation, rs.atoc,
coalesce(l.startlocation, rs.startlocation) as startlocation,
l.goodlocation
FROM railstp rs LEFT JOIN
location l
ON rs.startlocation = l.startlocation
WHERE rs.startdate = '2013-09-28'
ORDER BY startdate

Count the number of rows in MySQL table with criteria depending on other table

I've got two tables:
content:
id access
1 3
2 5
3 9
viewlevels:
id group
1 [10,12,15]
2 [8,12,11]
3 [9,10,5]
The access field in content is related with the id field in viewlevels.
I select the rows in viewlevels depending on the current user group. So for example, if group is = 10, my query will select rows 1 and 3. If the group is 12, it will select rows 1 and 2, etc. I'm using the following query:
$query="SELECT id FROM #__viewlevels WHERE rules LIKE '%$group%'";
My challenge is to count the number of rows for column id in table content where the access matches with the selected id's from the above query on table viewlevels.
I tried the following code but it is returning the error: undefined variable: nartigos
$query="SELECT count(id) FROM #__content WHERE access IN (SELECT id FROM #__viewlevels WHERE rules LIKE '%$group%')";
if ($stmt = mysqli_prepare($link, $query)) {
/* execute query */
mysqli_stmt_execute($stmt);
/* store result */
mysqli_stmt_store_result($stmt);
$nartigos=mysqli_stmt_num_rows($stmt);
/* close statement */
mysqli_stmt_close($stmt);
};
echo "Nº de artigos " .$nartigos;
First of all, you really should normalize your data. Consider having a many-to-many join table for viewLevels instead of having all groups in one row. That might look like this:
access_id group_id
1 10
1 12
1 15
2 8
2 11
2 12
3 5
3 9
3 10
That would make your query as simple as
SELECT c.id AS `content_id`, COUNT(v.access_id) AS `content_count`
FROM content AS c INNER JOIN viewLevels AS v
ON c.access_id = v.access_id
WHERE v.group_id = ?
GROUP BY c.id
Here ? is the group id you are querying against.
Without normalization (which again I STRONGLY recommend you do), you would still use a join, but it would look like this:
SELECT c.id AS `content_id`, COUNT(v.access_id) AS `content_count`
FROM content AS c INNER JOIN viewLevels AS v
ON c.access_id = v.access_id
WHERE v.group LIKE '%?%'
GROUP BY c.id
you need to "join" your tables.
the sql command cant query two tables seperately.
when you "join" 2 tables in your sql, think of it as making one virtual/temporary table in the air, of the 2 tables which you can then query.
this is quite a good intro http://www.sitepoint.com/understanding-sql-joins-mysql-database/

MySQL Query with JOIN Not executing correctly

I'm not getting any data, and I've checked my dad which should match up
I have two tables, likes and user_follow
I'm trying to tie the two tables by an id.
Table - Column
likes - idlikes, iduser, information
user_follow - iduser_follow, iduser_follower, iduser_following
$following = $dbh -> prepare("SELECT L.* FROM likes L JOIN user_follow F ON F.iduser_following = L.iduser WHERE F.iduser_follower = ?");
$following->execute(array($_SESSION['user_auth']));
while($row_following = $following->fetch(PDO::FETCH_ASSOC)){
$id_1 = $row_following['L.information']; // get id of user that i'm following
echo $id_1;
}
So if i'm following someone, i should be able to display information associated with whomever I'm following.
I don't get any errors, it just doesn't echo out anything?
Sample Data
user_follow
iduser_follow iduser_follower iduser_following
1 2 3
2 2 4
likles
idlikes iduser information
1 3 info1
2 3 info2
So, I should output info1 and info2, assuming that $_SESSION['user_auth'] = 2, correct?
SELECT b.*
FROM user_follow a
INNER JOIN likes b
ON a.iduser_following = b.iduser
WHERE a.iduser_follow = 'myuserID' AND
iduser_following = 'followingID'
and fetch value
$id_1 = $row_following['information'];

Categories