I have this loop in PHP to select all my scores from my game from a MySQL table.
My query is:
$sql = "SELECT * FROM $table WHERE ";
switch($type) {
case "global":
$sql .= "1 ";
break;
case "device":
$sql .= "udid = '$udid' ";
break;
case "name":
$sql .= "name = '$name' ";
break;
}
$sql .= "ORDER BY $sort ";
$sql .= "LIMIT $offset,$count ";
$result = mysql_query($sql,$conn);
The udid is a unique identifier. And the loop:
while ($row = mysql_fetch_object($result)) {
echo '<tr>
<td>
'.$rank.'
</td>
<td>
'.$row->name.'
</td>
<td>
'.$row->score.'
</td>
<td>
'.$row->udid.'
</td>
</tr>';
$rank++;
}
My question is simple, so a person can see inside the game at which rank he is.
"How to select a rank from a udid, outside of the loop".
Perhaps making a new query which selects the rank from a udid, or set up a variable from in the loop?
Here's how to query the database for the rank for player udid 1:
SELECT COUNT(*) AS rank
FROM tablename
WHERE score > (SELECT score FROM tablename WHERE udid = 1)
I'm assuming a higher score is better and you're only storing the highest score for each player.
With an index on score and udid, this should be pretty speedy.
What the query does is count the number of users who have a greater score than the selected user.
If a lower score is better, simply change it to this:
SELECT COUNT(*) AS rank
FROM tablename
WHERE score < (SELECT score FROM tablename WHERE udid = 1)
Which counts the number of players with a lower score.
Read all about MySQL indexes.
One option is writing a function that calculate the user's rank based on all the other's scores and returning it.
Then , calling it when the user wants to see his rank.
As far as I know , MMORPG games (for instance) have a rank field in their DB for each
player and they use a daily or hourly cron-job to update that rank.
So instead of running the 'calculate-the-rank' function each and every time a player
just want to see his rank, you'll just need to fetch the value of the field.
EDIT: code for the function (don't forget to add the rank field to your DB table)
File:
cronjob_update_rank.php:
require 'config.php'; //Or whatever contains your config and DB connection.
$rank = 1; //The best player ranked as 1
$getMembers = mysql_query("SELECT id FROM members ORDER BY `score` DESC");
while($mem = mysql_fetch_array($getMembers))
{
mysql_query("UPDATE members SET rank='$rank' WHERE id='{$mem['id']}'");
$rank++;
}
Please notice , it's just a sample code , you'll need to customize it for your needs.
Use your server panel to create a daily cronjob on that file.
(or ask for your hosting provider support with it).
Related
I've a table that has three columns id, points, rank. Timely I update data for all fields so points go up and down but old rankings remains same, so I'm trying to find out a way that entitles each id its deserving rank based on points earned.
I've got more than 2000 rows in this table. I wish to do it in php5+ with mysqli? I think I've a solution but it times out even with 1200 seconds timeout setting and memory gets exhausted.
I think my solution works accurately but any of the loops needs some doctor. Here my rough target is 'update' query to go accurate that takes all points in desc order, and awards id a rank against the points earned:
<?php
require_once $_SERVER['DOCUMENT_ROOT'].'/includes/db.inc.php';
$a2= mysqli_query($link, "SELECT COUNT(*) as count FROM p1");
$b2 =mysqli_fetch_array($a2);
$count = $b2['count'];
$i=1;
while($i<=$count){
$a1= mysqli_query($link, "SELECT points FROM p1 ORDER BY points DESC LIMIT $i");
if(!$a1){
echo mysqli_error($link);
}
while($po = mysqli_fetch_array($a1)){
$ross[] = $po;
}
foreach($ross as $pot){
$points=$pot['points'];
}
$a5a= mysqli_query($link, "SELECT id FROM p1 WHERE points = '$points'");
while($popo = mysqli_fetch_array($a5a)){
$idi=$popo;
}
foreach($idi as $idm){
$id=$idm['id'];
$rank = $i;
$update = mysqli_query($link,"UPDATE p1 SET rank = '$rank' WHERE points = '$points' AND id ='$id'");
}
if(!$update){
echo "Error updating Rank".mysqli_error($link);
} else {
echo "Succuessul for where id = '$id' and points = '$points' set rank = '$rank'<br/>";
}
$i++;
}
?>
I have replaced my original answer with much leaner and shorter code, you can of course include modification to the rank counter if consecutive users have same points but you can figure this yourself
This code have just one loop and is conserving memory and your DB as well
<?php
require_once $_SERVER['DOCUMENT_ROOT'].'/includes/db.inc.php';
$a = mysqli_query($link, "SELECT id, points, rank FROM p1 ORDER BY points DESC "); // lets get users in new ordering
$rank = 1; // new ranks
while($line = mysqli_fetch_array($a)){
if ($rank != $line["rank"]) { //if old rank is different we will hit db with new value
echo "updating id ".$line["id"]." from rank ".$line["rank"]." to rank ".$rank." <br>";
if(!mysqli_query($link,"UPDATE p1 SET rank = '".mysqli_real_escape_string($link,$rank)."' WHERE id ='".mysqli_real_escape_string($link,$line["id"])."'")) {
echo "Error updating Rank".mysqli_error($link);
}
}else { //if its the same we just leave the message for now
echo "ignoring id ".$line["id"]." previous rank ".$line["rank"]." , new rank ".$rank." <br>";
}
$rank++; // next user so lets increment the counter
}
?>
Recently went through same kind of issue and found a simple solution like below after struggling a lot. I would like to clear it out that, it depends on your input and expected result as well which you didn't mention in your post.
if (preg_match('/"'.<value>.'"/i' , json_encode(<your array>))) {
echo "Match";
} else {
echo "Doesn't match";
}
Please replace values accordingly when trying! Thanks for reading it.
The following answer code takes all points, and relevant ids and sets high to low ranks against high to low points respectively. However, it does not assign same rank for same points holder id as it keeps rolling with Rank+1 until end. That could be done, but isn't presently required.
<?php
require_once $_SERVER['DOCUMENT_ROOT'].'/includes/db.inc.php'; //connection to the DB
$a1= mysqli_query($link, "SELECT id, points FROM p1 ORDER BY points DESC"); //Selecting High to low all points
if(!$a1){
echo mysqli_error($link);
}
while($po = mysqli_fetch_array($a1)) {
$rose[] = $po;
}
$rank=0;//set rank 0
foreach($rose as $ro) { //splitting each row of array with unlimited rows
$points=$ro['points'];
$id=$ro['id'];
$rank++; //adding 1 each time foreach loops repeats itself until no row left
$update = mysqli_query($link,"UPDATE player1 SET rank = '$rank' WHERE points = '$points' AND id ='$id'"); //sending update command
if(!$update) { //echoing out what the hell this code is f******
echo "Error updating Rank".mysqli_error($link);
} else {
echo "Succuessul for where id = '$id' and points = '$points' set rank = '$rank'<br/>";
}
}
?>
WRT: how to insert records for top 10 enteries only
This is more refined question.
I have gathered top 10 users for specific task. Using the query given below.
mysql_query("SELECT `userid`, SUM(`points`) as `total` FROM
`tablename` GROUP BY `userid` ORDER BY total DESC LIMIT 10");
Now , I need to award bonues to the top 3 gathered users only, out of these selected top 10. I am not getting the idea , on how to write query for this purpose.
The top 3 bonuses are different for top 3
1: First user gets 1000 points
2: 2nd user gets 500 points
3: 3rd user gets 100 points
I need to update one field in tablename = user , field name = points.
To update the bonus i am using the below query(general query):
$Db1->query('UPDATE user SET points=points+'.$rate.'
WHERE userid = '.$credituser);
I hope this question is well elaborated as per the community standards.
Kindly guide.
Working on a pure MySQL version.
As you've PHP tagged, I'll incorporate that into my answer :)
(Ps: Don't use mysql_*. As OP used mysql_*, my answer will)
Fetch the results
Loop through the results
Update the results depending on their position
$objGet = mysql_query("SELECT `userid`, SUM(`points`) as `total` FROM
`tablename` GROUP BY `userid` ORDER BY total DESC LIMIT 10");
if( mysql_num_rows($objGet) ) {
$intIteration = 1;
while( $arrResults = mysql_fetch_assoc($objGet) ) {
switch($intIteration) {
case 1 :
mysql_query("UPDATE tablename SET points = points + 1000 WHERE userid = ". $arrResults['userid']);
break;
case 2 :
mysql_query("UPDATE tablename SET points = points + 500 WHERE userid = ". $arrResults['userid']);
break;
case 3 :
mysql_query("UPDATE tablename SET points = points + 100 WHERE userid = ". $arrResults['userid']);
break;
default:
//No idea.
//Not in the top 3.
break;
}
$intIteration++;
}
} else {
//No users.
}
This question already has answers here:
Rank function in MySQL
(13 answers)
Closed 8 years ago.
I have a text based mafia game and I am selected some GameRecords. The game records are all defined in the "users" table. For this example I am using "totalcrimes". I need to select all the rows from the users table and order it by totalcrimes and then find out which row each specific user is that is viewing the page.
If I was the user that was "ranked" 30th it would echo "30". The code I use to find the top 5 is here however I need to expand on it:
<?php
$i = 0;
$FindCrimes = mysql_query("SELECT * FROM players WHERE status='Alive' AND robot = 0 ORDER BY `totalcrimes` DESC LIMIT 5");
while($Row = mysql_fetch_assoc($FindCrimes)){
$Username = $Row['playername'];
$TotalCrimes = number_format($Row['totalcrimes']);
$i++;
echo "
<tr>
<td bgcolor='#111111' width='5%'>$i</td>
<td bgcolor='#111111' width='50%'><a href='viewplayer?playerid=$Username'>$Username</a></td>
<td bgcolor='#333333' width='45%'>$TotalCrimes</a></td></td>
</tr>
";
}
?>
I am going to assume that you already have a variable set to hold the current users ID number and total crimes, so in this case I will use $user as my variable.
Change yours to fit.
Now, I see 2 instances in which you could mean as your post wasn't very specific, so I will address both.
To show the number at the top of the page, you would use something like;
<?php
$sql = "SELECT * FROM `players` WHERE `totalcrimes` > '{$user['totalcrimes']}'";
$run = mysql_query($sql);
$rank = mysql_num_rows($run) + 1;
echo 'Your rank: ' . $rank;
Other than that, I see it's possibly being used to highlight your row, so something like this would suffice;
<?php
$i = 0;
$FindCrimes = mysql_query("SELECT * FROM players WHERE status='Alive' AND robot = 0 ORDER BY `totalcrimes` DESC LIMIT 5");
while($Row = mysql_fetch_assoc($FindCrimes))
{
$Username = $Row['playername'];
$TotalCrimes = number_format($Row['totalcrimes']);
$i++;
$primary = '#111111';
$secondary = '#333333';
if ($Row['id'] == $user['id'])
{
$primary = '#222222';
$secondary = '#444444';
}
echo "<tr>
<td bgcolor='$primary' width='5%'>$i</td>
<td bgcolor='$primary' width='50%'><a href='viewplayer?playerid=$Username'>$Username</a></td>
<td bgcolor='$secondary' width='45%'>$TotalCrimes</a></td></td>
</tr>";
}
If neither of those give your requirements, please comment and I'll edit to suit.
edit: I've worked on games for a few years - care to share the link to yours?
This can do the trick
SELECT COUNT(*)+1 as rank
FROM users
WHERE totalcrimes > (SELECT totalcrimes
FROM users
WHERE user_id='12345' AND status='Alive' AND robot='0');
So it counts all rows with greater totalcrimes than selected user (in this example I have used user_id column and some id 12345), than adds 1 on that sum and returns as rank value.
Course, modify WHERE clause inside the brackets to make it work for you.
I assumed that table name is users and user's id is integer user_id.
Test preview (Navicat Premium):
What this query does? It returns number of selected rows + 1 as rank column, from the table users where totalcrimes is greater than totalcrimes of some user. That user's totalcrimes is selected by another query (by its user_id). If you have multiple users with same totalcrimes value, this query will return same rank for all of them.
My data base is
http://i.imgur.com/p4wUP54.jpg
hey i m new here in php and i don't know how to find lowest unique bidder for a auction of a product and i want also display name of username of that lowest unique bidder.
please help me i have tried but some code that are follow
$con = mysql_connect("localhost","root","");
if (!$con)
{
die('Could not connect: ' . mysql_error());
}
mysql_select_db("gunjanbid", $con);
$sql="SELECT * from bid";
$result=mysql_query($sql);
$username=$result['userName'];
$serial=$result['serial'];
$low_sql = "SELECT bidamount,userName, COUNT(bidamount) as bid_count
FROM bid
WHERE bidamount<'{$serial}' AND bid_count=1 AND auction='{$username}'
GROUP BY bidamount";
$low_query = mysql_query($low_sql) ;
$low_bids = array();
if (mysql_num_rows($low_query) > 0)
{
$lower_bid_exist = true;
while ($row = mysql_fetch_assoc($low_query))
{
$low_bids[$row['bidamount']] = $row['bid_count'];
}
} else {
$lower_bid_exist = false;
}
?>
Lowest Unique Bidder :<?php echo $row['userName']; ?>
Try this:
SELECT bidamount,userName, bidamount as bidamount
FROM bid WHERE bidamount = (SELECT MIN(bidamount) FROM bid) ORDER BY closing_date LIMIT 1
OK. So, firstly, you need to approach this issue with a tiny bit of planning.
Your requirements are:
- The bid amount must be unique
- You want to select the lowest bid amount
There are quite a few ways to do this. I will show you the simplest (SQL wise) way to solve your issue in a single query (with subquery).
This is NOT the best way - as I would ordinary suggest two separate queries, but this will get you what you want in a single row return.
http://sqlfiddle.com/#!2/2e978/10
SQL becomes:
select
bidamount,
username
from
bid
where
-- for the auction in question
auction = '$username'
and bidamount = (
select
min(lowest_bid.bidamount)
from
bid lowest_bid
where
lowest_bid.auction = '$username'
group by
lowest_bid.bidamount
having
count(distinct lowest_bid.username) = 1
order by
bidamount
limit 1);
So, I thought I was getting pretty good at MySQL until I ran into this idea:
I have a table logging "votes" (aptly named votes) with these fields:
id: The vote's unique ID.
user: Unique User ID of the person who voted
item: ID of item they're voting on
vote: The vote they cast SET('up','down')
Now, I'm trying to come up with an SQL way to find users whose only votes are downvotes. I know of a way to write it procedurally in php after querying most of the data out of the table but it seems really, really inefficient to do that way when only a few queries could find this out.
Ideally I want my result to just be a list of users who have 0 upvotes (as being in the table means they have voted, so they only downvote) and maybe the number of downvotes they've cast.
Any ideas on how I should approach this?
SELECT user, SUM(IF(vote='down',1,0)) AS numDownVotes
FROM votes
GROUP BY user
HAVING SUM(IF(vote='up',1,0))=0 -- 0 upvotes
AND SUM(IF(vote='down',1,0))>0 -- at least 1 downvotes
I can't help but feel there's a neat GROUP BY user, vote way to do this though.
I haven't checked the syntax or anything, but this comes to mind...
SELECT user
FROM votes
GROUP BY user
HAVING SUM(IF(vote = 'up', 1, 0)) = 0
AND SUM(IF(vote = 'down', 1, 0)) > 0
select user, count(user)
from votes
where user not in (
select distinct user
from votes
where votes = 'up')
select v.user from votes v where
0=(select count(a.vote) from votes a where a.user=v.user and a.vote='up' group by user) u
and
0 <(select count(a.vote) from votes a where a.user=v.user and a.vote='down' group by user) d
group by user;
Anything wrong with doing it on the database call? Something like:
$query = "SELECT id FROM votes WHERE vote = 'down'";
$result = mysql_query($query);
while ($rows = mysql_fetch_assoc($result))
{
$curID = $rows['id'];
}
<?php
// Make a MySQL Connection
$query = "SELECT user, COUNT(user) FROM votes where vote == 'down' GROUP BY user";
$result = mysql_query($query) or die(mysql_error());
// Print out result
while($row = mysql_fetch_array($result)){
echo "User : ". $row['type'] ." has ". $row['COUNT(user)'] ." downvote/s.";
echo "<br />";
}
?>