MySQL highscore query [duplicate] - php

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
mySQL “Rank in Highscore”-Query
I was just wondering if there is any effective way to gather the current rank of some id based on points.
My only idea was to grab whole points and then check every record if its more or less. Something like this.
Select * from whatever table
$x=0
while($row = mysql_fetch_array($result) {
if ($user == $row['user']) {
echo "$user is rank $x out of " . count($result);
break;
}
else {
$x++
}
}

You can use a variable, as shown here:
SET #rank=0;
SELECT user.*, #rank:=#rank+1 AS 'rank'
FROM user
ORDER BY score DESC

Do you mean like the "MAX" in mysql?
"SELECT max(score) as record FROM users";
This will retrieve a column with the highest score from the users table.

this can be done in mysql:
SELECT ui2.*,
(
SELECT COUNT(*)
FROM users ui
WHERE (ui.points, ui.id) >= (ui2.points, ui2.id)
) AS rank
FROM users ui2
WHERE id = #id

Yes you can use max() along with the group by clause to group the results based on certain criteria.
"SELECT max(score) as record FROM users_points group by user_id, game_id";

drop table if exists users;
create table users
(
id int unsigned not null auto_increment primary key,
score int unsigned not null default 0
)
engine=innodb;
insert into users (score) values (10),(30),(50),(30),(20),(45),(20);
select
#r:=#r+1 as rank,
u.id,
u.score
from
users u
inner join (select #r:=0) as r
order by
u.score desc;

Related

MySQL: Use my defined aggregated field in sub select

I have a query that want to compute each user_id's rank in comparison to all all other user_id real time. Real-time means when query is executing:
My query is as below, but unfortunately computed rank field is not as desired:
SELECT user_id, SUM(COALESCE(`duration`, 0)) AS duration_total,
(SELECT COUNT(*)
FROM `forms`
GROUP BY `user_id`
HAVING SUM(`duration`) > duration_total
) AS rank
FROM `forms`
GROUP BY `user_id`
The problem is on Having condition in the internal select. Where I want to count user_id that have more duration than current user_id.

Need to perform ORDER BY twice, problems with ranking

I have been struggling to set this up for months and months!
I need help with setting rank to my database.
This is how my current code looks like:
$db->queryNoReturn("SET #a:=0");
return $db->query("
SELECT * FROM
(SELECT
`FFA_Stats`.`id`,
`FFA_Stats`.`player_uuid`,
`FFA_Stats`.`points`,
`FFA_Stats`.`hits`,
`FFA_Stats`.`shots`,
`FFA_Stats`.`wins`,
`FFA_Stats`.`tkills`,
`FFA_Stats`.`tdeaths`,
(`FFA_Stats`.`tkills`/`FFA_Stats`.`tdeaths`) as `KDR`,
`player`.`name`,
`player`.`uuid`,
`player`.`online`,
(#a:=#a+1) AS rank
FROM `FFA_Stats`
INNER JOIN `player` ON `FFA_Stats`.`player_uuid`=`player`.`uuid`
ORDER BY `points` DESC
) AS `sub`
");
Basically its sorting it by points and you can check how it looks like here: http://filipvlaisavljevic.com/clash/ffa.php
All I want to do is add rank to the sorted table so the player with the most points would be #1 etc.
Does anyone know what to do?
Usually a rank number would be an integer that you could generate from iterating through the rows of the query result. eg. echo $count++;
If you have calculated or attributed a rank in your database then you can add 'order by' statements separated by commas. eg.
FROM `FFA_Stats`
INNER JOIN `player`
ON `FFA_Stats`.`player_uuid`=`player`.`uuid`
ORDER BY `rank` DESC, `points` DESC) AS `sub`
");

Query first, then randomize, and then retrieve remaining fields [duplicate]

This question already has answers here:
MySQL: Alternatives to ORDER BY RAND()
(9 answers)
How to request a random row in SQL?
(30 answers)
Closed 6 years ago.
I have a table with about 70 columns and 120,000 rows of data. What I want to do is randomize a record and then displaying the values of others columns of this record.
If I do fetch all data,
$result=mysqli_query($link, 'SELECT id, column1, column2, column3, ..., column 70 from table');
while ($row=mysqli_fetch_array($result))
{
$info[] = array('id'=>$row['id'], 'column1'=>$row['column1'], ...);
}
$randindex = rand(0,count($info));
$id = $info[$randindex]['id'];
echo $info[$randindex]['column1']; echo $info[$randindex]['column2']; ....
I'm afraid that this will significantly slow down the process. So I want to query only the ID before randomization, and then use the randomized ID to retrieve the other values of that record in the database.
$result=mysqli_query($link, 'SELECT id from table');
while ($row=mysqli_fetch_array($result))
{
$info[] = $row['id'];
}
$randindex = rand(0,count($info));
$id = $info[$randindex];
and then retrieve all other fields of this particular record somehow. I asked how to do this in SQL here but I would like to know if there is any more efficient way by other means besides SQL. Do I need to do a loop like this?
In your code, do the following:
select min(id) as minid, max(id) as maxid
from table;
Then use php to generate a random id and do:
select t.*
from table t
where t.id >= $randid
order by id
limit 1;
With an index on id -- and reasonable assumptions about there not being too large gaps in the values -- then this will work well.
You can do the same thing in just one query:
select t.*
from table t cross join
(select min(id) as minid, max(id) as maxid from table) tt
where t.id >= minid + rand() * (tt.maxid - tt.minid)
order by id
limit 1;
you can use ORDER BY RAND() directly in the sql query:
SELECT * FROM table ORDER BY RAND() LIMIT 1
ORDER BY RAND() actually makes random order of you rows, and then you just do LIMIT 1 in order to get only one row, the first one.
I do not think it is valid. I think it's faster execute just one query with ORDER BY RAND ()

Calculate Rank with points

I have a database with users and points (in fact it's a percentage, but that doesn't matter). The user(s) with the highest number of points is on the first rank, the second on the second rank ...
I could get the rank of a $searchedUserID if I did somethink like this:
SELECT `user_id`, `points` FROM `usertable` ORDER BY `points` DESC
/** This function returns the rank of a user. The rank nr. 1 is the best.
* It is possible that some users share a rank.
*
* #param int $searchedUserID the ID of the user whose rank you would like to
* know
*
* #return int rank
*/
function getUserRank($searchedUserID)
{
$userArray = getAllUsersOrderedByPoints();
$rank = 0;
$lastPoints = -1; // Never happens
foreach ( $userArray as $user) {
if ($user['point'] != $lastPoints) $rank++;
if ($user['user_id'] == $searchedUserID) break;
}
return $rank;
}
Isn't there a more direct way to get this with (My)SQL?
If not: Can the PHP-part be improved?
(edit: I could store the rank calculated by PHP directly in the database ... but this would mean I had to make quite a lot of UPDATEs.)
edit2: Perhaps GROUP BY could be used? Something like:
SELECT `user_id`, `points` FROM `usertable` GROUP BY `points` ORDER BY `points` DESC
The problem with this query is the possibility, that I don't get the searched user_id. It would be necessary to send a second query:
SELECT `user_id` FROM `usertable` WHERE `points` = $pointsOfTheUser
You ask:
Isn't there a more direct way to get this with (My)SQL?
Yes. In SQL:2003, you could use the DENSE_RANK() window function. In MySQL, you can simulate this, as the (dense) rank of a record by some score is simply the count + 1 of distinct better scores:
SELECT u.user_id,
u.points,
1 + COUNT(DISTINCT others.points) AS `dense_rank`
FROM users u
LEFT JOIN users others
ON u.points < others.points -- Which other users have more points?
WHERE user_id = ?
GROUP BY 1, 2;
perhaps an inner join with group by and sort would do the trick?
SELECT * FROM
INNER JOIN
(
SELECT user_id AS uid, max(points) AS score
FROM usertable GROUP BY user_id
)
AS ds ON usertable.user_id = ds.uid AND usertable.points = ds.score
ORDER BY score DESC
Just thinking on paper (pixels) .. wouldn't that give you the list in order from highest points to lowest with a unique record per user ... or are you looking to have these sorted where you can clarify a tie as a single "place" in the rankings?

SQL position of row(ranking system) WITHOUT same rank for two records

so I'm trying to create a ranking system for my website, however as a lot of the records have same number of points, they all have same rank, is there a way to avoid this?
currently have
$conn = $db->query("SELECT COUNT( * ) +1 AS 'position' FROM tv WHERE points > ( SELECT points FROM tv WHERE id ={$data['id']} )");
$d = $db->fetch_array($conn);
echo $d['position'];
And DB structure
`id` int(11) NOT NULL,
`name` varchar(150) NOT NULL,
`points` int(11) NOT NULL,
Edited below,
What I'm doing right now is getting records by lets say
SELECT * FROM tv WHERE type = 1
Now I run a while loop, and I need to make myself a function that will get the rank, but it would make sure that the ranks aren't duplicate
How would I go about making a ranking system that doesn't have same ranking for two records? lets say if the points count is the same, it would order them by ID and get their position? or something like that? Thank you!
If you are using MS SQL Server 2008R2, you can use the RANK function.
http://msdn.microsoft.com/en-us/library/ms176102.aspx
If you are using MySQL, you can look at one of the below options:
http://thinkdiff.net/mysql/how-to-get-rank-using-mysql-query/
http://www.fromdual.ch/ranking-mysql-results
select #rnk:=#rnk+1 as rnk,id,name,points
from table,(select #rnk:=0) as r order by points desc,id
You want to use ORDER BY. Applying on multiple columns is as simple as comma delimiting them: ORDER BY points, id DESC will sort by points and if the points are the same, it will sort by id.
Here's your SELECT query:
SELECT * FROM tv WHERE points > ( SELECT points FROM tv WHERE id ={$data['id']} ) ORDER BY points, id DESC
Documentation to support this: http://dev.mysql.com/doc/refman/5.0/en/sorting-rows.html
Many Database vendors have added special functions to their products to do this, but you can also do it with straight SQL:
Select *, 1 +
(Select Count(*) From myTable
Where ColName < t.ColName) Rank
From MyTable t
or to avoid giving records with the same value of colName the same rank, (This requires a key)
Select *, 1 +
(Select Count(Distinct KeyCol)
From myTable
Where ColName < t.ColName or
(ColName = t.ColName And KeyCol < t.KeyCol)) Rank
From MyTable t

Categories