Sort MySQL query in PHP - php

I'm trying to sort different users 'points' by descending order (highest first). But at the moment the query is being returned in order of the user's ID (order they appear in the database). I'm not sure what is wrong with my code?
The user can be in multiple leagues, so it first queries to see what leagues that the particular user is in. With the league IDs, I query to see what users are in each of the leagues. Then I query what each users total points are within that league. Ultimately, I want to get the rank of the user for each league but at the moment the query to order by the points is not working.
The image shows how the points are coming out. '1635' is the users points that is logged in. For the first league, I'm trying to get 'rank 2' displayed.
// SQL query to see what leagues user is in
$query = mysqli_query($con, "SELECT * FROM UserLeague WHERE UserID='$userid'");
$num = mysqli_num_rows($query);
if($num == 0) {
echo 'You are not in any leagues';
return;
} else {
echo '<div class="pleague-table">';
echo '<div class="pleague-table-header">';
echo '<p>PRIVATE LEAGUE</p>';
echo '<p>CURRENT RANK</p>';
echo '</div>';
}
while($leagueid = mysqli_fetch_assoc($query)) {
$lid = $leagueid['LeagueID'];
// Get all league info that user is in
$query2 = mysqli_query($con, "SELECT * FROM League WHERE LeagueID='$lid'");
// Get all users that is in each league
$queryposition = mysqli_query($con, "SELECT UserID FROM UserLeague WHERE LeagueID='$lid'");
while($getpoints = mysqli_fetch_assoc($queryposition)) {
$uid = $getpoints['UserID'];
// Get each users points in each league
$querypoints = mysqli_query($con, "SELECT * FROM Points WHERE UserID='$uid' ORDER BY total DESC");
while($row = mysqli_fetch_assoc($querypoints)) {
echo $row['total']. '</br>';
}
}
while($leaguename = mysqli_fetch_assoc($query2)) {
echo '<div class="league-link">';
echo $leaguename['Name'];
echo 'Options';
echo '</div>';
}
}
'''

You are trying to combine 2 tables: UserLeague and Points to select users from UserLeague and order them by Points. For such cases there is JOIN syntax in SQL:
SELECT Points.*
FROM Points
RIGHT JOIN UserLeague ON Points.UserID=UserLeague.UserID
WHERE UserLeague.LeagueID=?
ORDER BY Points.total DESC

Related

Pull data from table then echo it in descending order

I have the following table in my database
click to view
I'm looking to find everyone whose user_group is "member", then put their ratings in an array and print their names in descending order based on their rating.
So in the example given, it would output ted67945<br>ted67942.
I currently have this code
function getInfo($info, $given_username) { // This is only used to get the rating of the given user
require($_SERVER["DOCUMENT_ROOT"]."/movies/scripts/db.php");
$result = mysqli_query($conn, "SELECT ".$info." FROM members WHERE username='$given_username'");
while ($row = mysqli_fetch_array($result)) { // for each member
return $row[$info];
}
}
$result = mysqli_query($conn, "SELECT username FROM members WHERE user_group='member'") or die(mysql_error());
$ratings = Array();
while ($row = mysqli_fetch_array($result)) { // for each member
$name = $row['username'];
if(!empty($name)) {
array_push($ratings, getInfo("rating", $name)); // This puts all people's ratings in group "member", into an array
}
}
rsort($ratings);
foreach($ratings as $x) {
echo $x . "<br>";
}
This, obviously, outputs the numbers. How would I use this to output the names based on their rating?
Why can't you just use ORDER BY in your SQL request?
SELECT username FROM members WHERE user_group='member' ORDER BY rating DESC;
This will sort your data by rating in descending order. See more.

How to mysqli_fetch_row while using mysqli_multi_query

I'm trying to get the latest info about some specific person, and I'm using a query like
SELECT * FROM Table WHERE Name LIKE 'Peter' ORDER BY ID DESC LIMIT 1
and
SELECT * FROM Table WHERE Name LIKE 'Mary' ORDER BY ID DESC LIMIT 1
because in the Table each day will insert new data for different person at the instant of updating it (for record reference), so I would like to print out a few persons latest info by "ORDER BY ID DESC LIMIT 1"
I have tried to print it out with "mysqli_multi_query" and "mysqli_fetch_row"
like
$con=mysqli_connect($localhost,$username,$password,'Table');
$sql = "SELECT * FROM Table WHERE Name LIKE 'Peter' ORDER BY ID
DESC LIMIT 1 ";
$sql .= "SELECT * FROM Table WHERE Name LIKE 'Mary' ORDER BY ID
DESC LIMIT 1";
// Execute multi query
if (mysqli_multi_query($con,$sql))
{
do
{
// Store first result set
if ($result=mysqli_store_result($con)) {
// Fetch one and one row
while ($row=mysqli_fetch_row($result))
{
echo '<tr>'; // printing table row
echo '<td>'.$row[0].'</td>';
echo '<td>'.$row[1].'</td>';
echo '<td>'.$row[2].'</td>';
echo '<td>'.$row[3].'</td>';
echo '<td>'.$row[4].'</td>';
echo '<td>'.$row[5].'</td>';
echo '<td>'.$row[6].'</td>';
echo '<td>'.$row[7].'</td>';
echo '<td>'.$row[8].'</td>';
echo '<td>'.$row[9].'</td>';
echo '<td>'.$row[10].'</td>';
echo '<td>'.$row[11].'</td>';
echo '<td>'.$row[12].'</td>';
echo '<td>'.$row[13].'</td>';
echo '<td>'.$row[14].'</td>';
echo'</tr>'; // closing table row
}
// Free result set
mysqli_free_result($result);
}
}
while (mysqli_next_result($con));
}
mysqli_close($con);
?>
In the result page , it doesn't show any error message , but no results are printed.
The individual queries were tested.
Please advise, much thanks
Is there another way to keep the query simple, so there is no need to use mysqli_multi_query?
Best practice indicates that you should always endeavor to make the fewest number of calls to the database for any task.
For this reason, a JOIN query is appropriate.
SELECT A.* FROM test A INNER JOIN (SELECT name, MAX(id) AS id FROM test GROUP BY name) B ON A.name=B.name AND A.id=B.id WHERE A.name IN ('Peter','Mary')
This will return the desired rows in one query in a single resultset which can then be iterated and displayed.
Here is an sqlfiddle demo: http://sqlfiddle.com/#!9/2ff063/3
P.s. Don't use LIKE when you are searching for non-variable values. I mean, only use it when _ or % are logically required.
This should work for you:
$con = mysqli_connect($localhost,$username,$password,'Table');
// Make a simple function
function personInfo($con, $sql)
{
$result = mysqli_query($con, $sql);
if(mysqli_num_rows($result) > 0)
{
while($row = mysqli_fetch_array($result))
{
echo '<table>
<tr>';
for($i=0; $i < count($row); $i++) echo '<td>'.$row[$i].'</td>';
echo '</tr>
</table>';
}
}
}
$sql1 = "SELECT * FROM Table WHERE Name='Peter' ORDER BY ID DESC LIMIT 1 ";
$sql2 = "SELECT * FROM Table WHERE Name='Mary' ORDER BY ID DESC LIMIT 1";
// Simply call the function
personInfo($con, $sql1);
personInfo($con, $sql2);

How can I count the rows in a table above a Certain Data Point?

I have made a leaderboard for a quiz ordered by their score and I want to show the position of the user. How could I count how many rows are above them in the table in order to determine their position? This code only works when people don't have the same score. If 2 people both have the high score, both will see themselves as number 2.
function firstPlace() {
include 'connection.php';
$sql="SELECT * FROM Users WHERE Email='$_SESSION[email]'";
$result=mysqli_query($connection,$sql);
while($row1=mysqli_fetch_array($result)) {
if(isset($row1[4])) {
$score=$row1[4];
}
}
$sql2="SELECT * FROM Users WHERE Email='$_SESSION[email]'";
$result2=mysqli_query($connection,$sql2);
$sql1="SELECT * FROM Users WHERE Score >= $score ORDER BY Score DESC";
$result1=mysqli_query($connection,$sql1);
$numRows=mysqli_num_rows($result1);
while($row=mysqli_fetch_array($result2)) {
if($row[5]!="") {
$src1="photos/".$row[5];
}
else {
$src1='images/profile-pic.png';
}
echo "
<a class='logo' href='index.php'><img src='$src1' class='bigProfilePic' id='logo' alt='Profile pic'></a>
<h1>$numRows</h1>
<h2>$row[1]</h2>
<h3>$row[4]<span>Kms</span></h3>";
}
$sql = 'SELECT count(id) FROM Users WHERE Score > ?';
$stmt = mysqli_prepare($sql);
$stmt->bind_param("i", $Score );
$stmt->execute();
$result = $stmt->get_result();
Will give you how many users have score higher than $score, you could of course also keep the query open for sql injction as the others if you want to

How to fetch record from mysql using last inserted id?

This is what i tried and it works fine..
$sql = "SELECT * FROM patient where id = (SELECT max(id) FROM patient)";
result = mysql_query($sql);
if (mysql_num_rows($result) > 0)
{
// output data of each row
while($row = mysql_fetch_assoc($result))
{
$patientid=$row["id"];
$patientname=$row["name"];
$patientrefer=$row["referto"];
$patientdisease=$row["disease"];
}
}
else
{
echo "0 results";
}
but whenever i replaced the query with
$sql = "SELECT * FROM patient where id = LAST_INSERT_ID()";
It always return 0 results.
In order to get last (latest) record from your table, you can do descending ORDER BY together with LIMIT:
SELECT * FROM patient ORDER BY id DESC LIMIT 0,1
You don't need LAST_INSERT_ID in that case at all. Moreover with concurrent inserts you cannot ensure that user's last insert is really the latest one by using LAST_INSERT_ID.

Need help calculating wins and losses from points scored

I am creating a website in php to log ping pong scores for my school, and currently the player who wins will log the WinnerID, LoserID, PointsFor, PointsAgainst. I have two tables with the following relationships.
Table: users
user_ID (PK)
username
Elo
Table: games
game_id (PK)
WinnerID (FK)
LoserID (FK)
PointsFor
PointsAgainst
My insert statement in the php file is:
INSERT INTO games(WinnerID,LoserID,PointsFor,PointsAgainst) VALUES('$Winner_ID','$Loser_ID','$userscore','$oppscore')"
Here is what I have tried, but it doesn't display the scores correctly.
SELECT min(u.username) 'Username', COUNT(g.WinnerID) 'Wins', sum(g.PointsFor) 'Points For', sum(g.PointsAgainst) 'Points Against', u.Elo 'Ranking'
from games g
LEFT JOIN users u
on g.WinnerID = u.user_id
Group by g.WinnerID
As you can see by the image above, the points for and points against totals don't add up. Currently, it only displays the stats for whoever was winner. Meaning if PlayerA wins 21-5, it will show up from the select statement, but PlayerB will not show a score of 5-21. Any help is appreciated.
PHP code for page to enter scores:
if(isset($_POST['btn-post']))
{
$opponent = $_POST["opponent"];
//$opponent = array_key_exists('opponent', $_POST) ? $_POST['opponent'] : false;
$userscore = mysql_real_escape_string($_POST['userscore']);
$oppscore = mysql_real_escape_string($_POST['oppscore']);
if($userscore != $oppscore)
{
if($userscore > $oppscore)
{
$Winner_ID = $_SESSION['user'];
$query = mysql_query("SELECT user_id FROM users WHERE username = '".$opponent."'");
$result = mysql_fetch_array($query) or die(mysql_error());
$Loser_ID = $result['user_id'];
$query1 = mysql_query("SELECT Elo FROM users WHERE user_id=".$_SESSION['user']);
$result1 = mysql_fetch_array($query1) or die(mysql_error());
$winnerRating = $result1['Elo'];
$query2 = mysql_query("SELECT Elo FROM users WHERE user_id=".$Loser_ID);
$result2 = mysql_fetch_array($query2) or die(mysql_error());
$loserRating = $result1['Elo'];
$rating = new Rating($winnerRating, $loserRating, 1, 0);
$results = $rating->getNewRatings();
if(mysql_query("UPDATE users SET Elo = " . $results['a'] . " WHERE user_id=".$_SESSION['user']))
{
}
else
{
?>
<script>alert('There was an error while entering winners(user) ranking...');</script>
<?php
}
if(mysql_query("UPDATE users SET Elo = " . $results['b'] . " WHERE user_id=".$Loser_ID))
{
}
else
{
?>
<script>alert('There was an error while entering losers(opp) ranking..');</script>
<?php
}
}
elseif($oppscore > $userscore)
{
$Loser_ID = $_SESSION['user'];
$query = mysql_query("SELECT user_id FROM users WHERE username = '".$opponent."'");
$result = mysql_fetch_array($query) or die(mysql_error());
$Winner_ID = $result['user_id'];
//get rating from user table in database
$query1 = mysql_query("SELECT Elo FROM users WHERE user_id=".$_SESSION['user']);
$result1 = mysql_fetch_array($query1) or die(mysql_error());
$loserRating = $result1['Elo'];
$query2 = mysql_query("SELECT Elo FROM users WHERE user_id=".$Loser_ID);
$result2 = mysql_fetch_array($query2) or die(mysql_error());
$winnerRating = $result1['Elo'];
$rating = new Rating($winnerRating, $loserRating, 1, 0);
$results = $rating->getNewRatings();
$results = $rating->getNewRatings();
if(mysql_query("UPDATE users SET Elo = " . $results['b'] . " WHERE user_id=".$_SESSION['user']))
{
}
else
{
?>
<script>alert('There was an error while entering losers(user) ranking...');</script>
<?php
}
if(mysql_query("UPDATE users SET Elo = " . $results['a'] . " WHERE user_id=".$Winner_ID))
{
}
else
{
?>
<script>alert('There was an error while entering winners(opp) ranking...');</script>
<?php
}
}
if(mysql_query("INSERT INTO games(WinnerID,LoserID,PointsFor,PointsAgainst) VALUES('$Winner_ID','$Loser_ID','$userscore','$oppscore')"))
{
?>
<script>alert('Your scores were successfully entered');</script>
<?php
}
else
{
?>
<script>alert('There was an error while entering your score...');</script>
<?php
}
}
else
{
?>
<script>alert('There cannot be a tie in ping pong, please re-enter your scores...');</script>
<?php
}
}
?>
Your query fails because it doesn't take into account the rows where the player loses. You can fix that by using unions. The following query should do what you want:
SELECT username AS "Username",
SUM(wins) AS "Wins",
SUM(PF) AS "Points For",
SUM(PA) AS "Points Against",
elo AS "Ranking"
FROM (
(SELECT users.user_ID,
users.username AS username,
COUNT(games.WinnerID) AS wins,
SUM(games.PointsFor) AS PF,
SUM(games.PointsAgainst) AS PA,
users.Elo AS elo
FROM users, games
WHERE games.WinnerID = users.user_ID
GROUP BY users.user_ID)
UNION ALL
(SELECT users.user_ID,
users.username AS username,
0 AS wins,
SUM(games.PointsAgainst) AS PF,
SUM(games.PointsFor) AS PA,
users.Elo AS elo
FROM users, games
WHERE games.LoserID = users.user_ID
GROUP BY users.user_ID)
) AS t
GROUP BY username
ORDER BY user_ID;
Note that in the "losing query" the field PointsAgainst should be counter as the player's "points for" and vice-versa.
Try it as an inner join, and get rid of the MIN() on the username column:
SELECT u.username, COUNT(g.WinnerID),
SUM(g.PointsFor), SUM(g.PointsAgainst), u.Elo
FROM users u, games g
WHERE u.user_id = g.WinnerID
GROUP BY u.username, u.Elo;
Also, before anyone else takes you to task, you should be using mysqli instead of mysql (or better yet, PDO) and you should be using prepared statements instead of dynamic SQL.
Your
INSERT INTO games(WinnerID,LoserID,PointsFor,PointsAgainst) VALUES('$Winner_ID','$Loser_ID','$userscore','$oppscore')
query contains the $userscore and $oppscore values in a potentially wrong order. The $Winner_ID and $Loser_ID may change in your conditional processing, but $userscore and $oppscore are not similarly flipped at that time.
Also your conditional structure is in general unnecessarily verbose. It seems like you should be able to just determine the winner and loser ID and score first, and then do all your processing once instead of resorting to error-prone copy-paste duplication of near-identical code.

Categories