Rank points based off the highest number in a row - php

I have a table called "member_points", which is set up like this:
|----|-------|----------|------------------------|
| id | uid | points | last_loggedin |
|----|-------|----------|------------------------|
| 1 | 1 | 5075 | 2012-08-02 02:04:00 |
|----|-------|----------|------------------------|
| 2 | 2 | 2026 | 2012-08-04 02:15:02 |
|----|-------|----------|------------------------|
I have a function below. I want the function to echo or return the rank like "Ranked #1" or "Ranked #2", based on the number in the row "points".
function getTopRanks($id) {
$sql = "SELECT MAX(points) AS toppoints FROM member_points";
$r = mysql_query($sql);
if ( $r !== false && mysql_num_rows($r) > 0 ) {
while ( $a = mysql_fetch_assoc($r) ) {
$points = stripslashes($a['toppoints']);
return ''.$points.'';
}
}
}
Can someone help me make this possible?

I think you are going to ranking user on the basis of points.
For such type of problem, i suggest you to first rank user on DESC order. Then pickup desire value form row.
function getTopRanks($id) {
$sql = "SELECT uid FROM member_points ORDER BY points DESC ";
$r = mysql_query($sql);
if ( $r !== false && mysql_num_rows($r) > 0 ) {
while ( $a = mysql_fetch_assoc($r) ) {
$points = stripslashes($a['toppoints']);
return ''.$points.'';
}
}
}
this will solve your problem.:)
UPDATE AS YOUR REQUIREMENTS:
function getTopRanksUser($id) {
$userPos ="Ranked position is:";
$count = 0;
$sql = "SELECT uid FROM member_points ORDER BY points DESC ";
$r = mysql_query($sql);
if ( $r !== false && mysql_num_rows($r) > 0 ) {
while ( $a = mysql_fetch_assoc($r) ) {
$count = $count+1;
$userPosCount = $userPos+$count;
return $userPosCount;
}
}
}
there should be return userPos+count. because count is increases up number of rows in table and the string ranked position is always remains same.
this will give result. Your can change return string according to your requirements. :)
thanks.

In your mysql query use ORDER BY (http://dev.mysql.com/doc/refman/5.0/en/sorting-rows.html)
so your query would become
SELECT points FROM member_points ORDER BY points DESC
this will sort the results from the query by the amount of points. (DESC will make them descending and ASC will make the result ascending).

Here's what I use for my rankings ... this code also takes into account ties and displays correctly. Just change "username" and "points" to your appropriate column names in your db and set the db connection vars: $hostName $databaseNanme $username and $password for you connection.
Hope this helps!
$sql1 = "SET #rnk=0; SET #rank=0; SET #scount=0;";
$sql2 = "SELECT username, points, rank FROM
(
SELECT AA.*,BB.username, points
(#rnk:=#rnk+1) rnk,
(#rank:=IF(#scount=points,#rank,#rnk)) rank,
(#scount:=points) newscount
FROM
(
SELECT * FROM
(SELECT COUNT(1) scorecount,points
FROM users GROUP BY points
) AAA
ORDER BY points DESC
) AA LEFT JOIN users BB USING (points)) A;";
try {
$conn = new PDO('mysql:host='.$hostName.';dbname='.$databaseName, $username, $password);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->query($sql1);
$data = $conn->query($sql2);
$standings = $data->fetchAll(PDO::FETCH_ASSOC);
} catch(PDOException $e) {
error_log( 'ERROR: ' . $e->getMessage() );
}
print_r($standings);

Related

Iterate each row and get the count php mysql

I have a row in mysql
Uid campid type
1 100 Type1
1 100 Type1
1 200 Type1
I need to get the count of each Type1 for each campid
ie)
For campid 100 with Type1 - count = 2
For campid 200 with Type1 - count = 1
Below i am getting the total count of all campid which i dont want.
$Impressionarr = [];
$imp_qry = "select count(*) as ImpressionCount from ClicksAndImpressions where Uid = 101655 and CampaignID = 109 and Type='Impression' ;";
$impData = $this->getClicksAndImpressionsTable()->CustomQuery($imp_qry);
if($impData[0]['ImpressionCount'] != '' || $impData[0]['ImpressionCount'] !=NULL ){
$impr_update = "UPDATE ClicksAndImpressions SET ImpressionCount = ". $impData[0]['ImpressionCount'] ." where Uid = 101655 and CampaignID =109 and Type='Impression' ;";
$impqryexecute= $this->getClicksAndImpressionsTable()->CustomUpdate($impr_update);
foreach($impData as $key=>$data2)
{
$data2['ImpressionCount'];
$Impressionarr[] = $data2;
}
}else{
return array("errstr" => "success.", "success" => 0, "Campaigns" => "No Impression Counts");
}
public function CustomQuery($id) {
$sql = $id;
foreach (($this->tableGateway->getAdapter()->driver->getConnection()->execute($sql)) as $row){
$results[] = $row;
}
return $results;
}
select count(uid) as total, type from ClicksAndImpressions group by campid
try with the above query

Is it possible to loop through the mysql table rows and check columns?

I have a "matrix" table with the following columns filled in.
matrix_id, user_id, position_1, position_2, position_3
1 1 1982 2251 5841
2 2 6204 0 0
3 3 0 0 0
4 4 0 0 0
I basically want to do the following.
Find a row with the lowest user_id and that has an empty position.
In the example above, that would be user_id 2 and position_2.
I update the row with a query.
I then move on to the next next empty position. Since user_id 2 still has an empty position_3, I update the row again with a query.
Since that row is complete, I move on to the next highest user_Id that has empty positions. In this case, it's user_id 3 and then user_id 4 the one after that.
I know I can do all of the above if I know what the user_id is. But assume in this case, I have no clue what the user_ids are. How would the queries look then?
Here is what I have so far.
$find_user = $db->prepare("SELECT * FROM matrix WHERE user_id > :user_id");
$find_user->bindValue(':user_id', 0);
$find_user->execute();
$result_user = $find_user->fetchAll(PDO::FETCH_ASSOC);
if(count($result_user) > 0) {
foreach($result_user as $row) {
$matrix_id = $row['matrix_id'];
$user_id = $row['user_id'];
$position_1 = $row['position_1'];
$position_2 = $row['position_2'];
$position_3 = $row['position_3'];
}
} else {
$errors[] = 'User Id not found in Matrix.';
}
$update_user = $db->prepare("UPDATE matrix SET position_2 = :position_2 WHERE user_id = :user_id");
$update_user->bindValue(':position_2', 1564;
$update_user->bindParam(':user_id', $user_id);
if($update_user->execute()) {}
This should go through all your users from smallest user_id to largest.
For each user it will check the relevant columns in order and apply a new value to the empty ones.
$new_val = 1999;
$result = $db->query("SELECT * FROM matrix ORDER BY user_id");
$users = $result->fetchAll(PDO::FETCH_ASSOC);
if(count($users) > 0) {
// prepare all the possible queries
// make use of prepare once execute many times
$stmt1 = $db->prepare("UPDATE `matrix` SET `position_1` = :pos WHERE `user_id` = :id");
$stmt2 = $db->prepare("UPDATE `matrix` SET `position_2` = :pos WHERE `user_id` = :id");
$stmt3 = $db->prepare("UPDATE `matrix` SET `position_3` = :pos WHERE `user_id` = :id");
foreach($users as $user) {
if ( $user['$position_1'] == 0 ) {
$stmt1->execute( array(':pos'=>++$new_val,':id'=>$user['user_id']) );
}
if ( $user['$position_2'] == 0 ) {
$stmt1->execute( array(':pos'=>++$new_val,':id'=>$user['user_id']) );
}
if ( $user['$position_3'] == 0 ) {
$stmt1->execute( array(':pos'=>++$new_val,':id'=>$user['user_id']) );
}
}
} else {
$errors[] = 'User Id not found in Matrix.';
}
You could reduce the rows to process by changing the query a bit to only find users with columns to fix
$result = $db->query("SELECT *
FROM matrix
WHERE position_1 = 0
OR position_2 = 0
OR position_3 = 0
ORDER BY user_id");
important thing here, is that you are working with the row, not columns
so check all the prerequisites and update the row.
$find_user = $db->prepare("SELECT * FROM matrix order by user_id asc");
$find_user->execute();
$result_user = $find_user->fetchAll(PDO::FETCH_ASSOC);
foreach($result_user as $row) {
$matrix_id = $row['matrix_id'];
$user_id = $row['user_id'];
$position_1 = $row['position_1'];
$position_2 = $row['position_2'];
$position_3 = $row['position_3'];
}
$str = ''
if (!$position_2){
$str = "position_2 = :position_2"
} else if (!$position_2 && !$position_3){
$str = "position_2 = :position_2 and position_3 = :position_3"
}
$update_user = $db->prepare("UPDATE matrix SET " . $str . " WHERE user_id = :user_id");
$update_user->bindValue(':position_2', 1564);
$update_user->bindValue(':position_3', 1564);
$update_user->bindParam(':user_id', $user_id);
if($update_user->execute()) {}
Also, get all the rows in the matrix table ordered by used_id and process every row, depending on your condition.

Ranking list with all the users

I have a database (GAMES) with userid, name, sports and points.
user1, football, 10 points -
user1, Basketball, 5 points
user2, footbal, 8 points -
user2, Baketball, 3 points
To get the rank of each user by each sports, I am using the following code which is working perfect:
$sql = "SELECT
sports,
FIND_IN_SET(footbal, (
SELECT GROUP_CONCAT(sports
ORDER BY points DESC)
FROM ".GAMES."
)
) AS rank
FROM ".GAMES."
WHERE userid = 1
";
Results:
user1 (1) (1 is the rank)
When I use user2 in WHERE I get: user2 (2)
Now I want a list like this (For more than 1000 users):
1- User1 (1)
2- User2 (2)
3- User15 (44)
3- ....
Any help will be appreciated. I you need more explanation, just ask.
I would do something like this:
$sqls = array();
foreach ($sports as $sport) {
$sqls[] = "SELECT name FROM ".GAME." WHERE sports='".$sport."' ORDER BY points ASC"
}
Then loop through slqs variable to get all the lists.
And finally, to get the parenthesis part, I would do when I will print the list.
You could have 1 select like this:
$sql = 'SELECT * from table_GAMES WHERE points >= 1000 ORDER BY name'
The result would have all users with more than or equal to 1000 sorted alphabetically. You can then display it like this:
$result = mysql_query($sql);
while ($row = mysql_fetch_assoc($result)) {
echo $row['name'];
echo ' (' . $row['points'] . ')';
}
MySQL does not really implement ranking in a convenient way. This is discussed, for example, here: ROW_NUMBER() in MySQL
In that thread linked above you can see some solutions you could try, or alternatively you could use some simpler SQL to get an ordered list and use PHP to calculate/count the ranks:
// ...
$sql = 'SELECT userid, sports, SUM(points) AS total_points FROM games GROUP BY userid, sports ORDER BY sports, SUM(points) DESC';
$result = $mysqli->query($sql);
$rank = null;
$last_sport = null;
$sports_ranking = array();
while($row = $result->fetch_object()) {
if($row->sports == $last_sport) {
$rank++;
} else {
$rank = 1;
}
$sports_ranking[$row->sports][] = array(
'userid' => $row->userid,
'rank' => $rank,
'total_points' => $row->total_points
);
}
echo('<pre>'); print_r($sports_ranking); echo('</pre>');
// ...
Wouldn't this work?
"SELECT * FROM GAMES WHERE userid = ".$userid." ORDER BY points DESC"
I don't see why you would need to use anything else, as you are just ordering by their points.
or if you also want to specify a sport,
"SELECT * FROM GAMES WHERE userid = ".$userid." AND sports = '".$sport"' ORDER BY points DESC"
You would need to use an array to loop through each sport then just use the above query again.
e.g.
$ranks = mysql_query("SELECT * FROM GAMES WHERE userid = ".$userid." AND sports = '".$sport"' ORDER BY points DESC", $database);
$count = 1;
while(list($userid, $name, $sport, $points) = mysql_fetch_row($ranks)) {
//formatting here. table row, paragraph etc or:
echo "$count - $name ($userid)";
$count++;
}

Fetch the row of next in rank to the “rank of last id”?

Need help!
Mysql query:
CREATE TABLE goal_implement( id INT, percent INT );
INSERT INTO goal_implement VALUES
(1,10),
(2,15),
(3,20),
(4,40),
(5,50),
(6,20);
My PHP code - this code display the result table below....
<?php
$query2 = "SELECT _id, percent, FIND_IN_SET( percent, (
SELECT GROUP_CONCAT( percent
ORDER BY percent DESC )
FROM goal_implement )
) AS rank
FROM goal_implement
ORDER BY id DESC
";
I want this block to be on focus for the comment: I need the php code; NOT mysql query...
$result2 = mysql_query($query2, $connection);
if($result2 === FALSE) {
die(mysql_error());
}
while($row = mysql_fetch_array($result2))
{
echo
"<tr>
<td>{$row['id']}</td>
<td>{$row['percent']}</td>
<td> {$row['rank']} </td>
</tr>\n";
}
?>
Result:
id percent rank
6 20 3
5 50 1
4 40 2
3 20 3
2 15 5
1 10 6
I don't know how to fetch the row(rank) that is next on the last id for example: last id's rank is 3!I want the result Below.....
Desired result using PHP:
4 40 2
Try this:
<?php
$result2 = mysql_query($query2, $connection);
if($result2 === FALSE) {
die(mysql_error());
}
// store rows by rank
// also get the last_id_rank from the first row
$by_ranks = array();
$last_id_rank = FALSE;
while($row = mysql_fetch_array($result2)) {
$by_ranks[$row['rank']][] = $row;
if ($last_id_rank === FALSE) {
$last_id_rank = $row['rank'];
}
}
// get the results
$get_results = function($by_ranks, $last_id_rank) {
// get a sorted array of that's smaller than $last_id_rank
$ranks = array_filter(array_keys($by_ranks), function($var) use($last_id_rank) {
return $var < $last_id_rank;
});
rsort($ranks); // sort ranks by descending order
// get the rank that is just smaller than $last_id_rank
if (sizeof($ranks) == 0) {
return array();
} else {
return $by_ranks[$ranks[0]];
}
};
$results = $get_results($by_ranks, $last_id_rank);
// display results
foreach ($results as $row) {
echo "<tr>
<td>{$row['id']}</td>
<td>{$row['percent']}</td>
<td> {$row['rank']} </td>
</tr>\n";
}
?>
Since you are using mysql_fetch_array(), why don't you use it's index?
$row['rank'][$incrementHere]
I thing we can filter data with HAVING clause
$query="SELECT id, percent, FIND_IN_SET( percent, (
SELECT GROUP_CONCAT( percent
ORDER BY percent DESC )
FROM goal_implement )
) AS rank
FROM goal_implement
HAVING id >".$last_id_rank."
ORDER BY id ASC limit 1";

PreparedStatement select with php not working as expected

I have this query:
SELECT id, result, ip_address, added_date
FROM results
WHERE course_id = (
SELECT id
FROM courses
WHERE course = 'informatica'
AND macro_course_id = (
SELECT id
FROM macro_courses
WHERE macro_course = 'scienze-matematiche-fisiche-e-naturali'
AND organization_id = (
SELECT id
FROM organizations
WHERE organization = 'universita-degli-studi-di-torino'
AND city_id = (
SELECT id
FROM cities
WHERE city = 'torino'
AND region_id = (
SELECT id
FROM regions
WHERE region = 'piemonte' ))))) ORDER BY id DESC
And i'm using this code to do it with a preparedstatement
public function getResults($region, $city, $organization, $macro_course, $course) { //works
//added_date=datetime : YYYY-MM-DD HH:mm:ss
echo "SELECT id, result, ip_address, added_date
FROM results
WHERE course_id = (
SELECT id
FROM courses
WHERE course = '$course'
AND macro_course_id = (
SELECT id
FROM macro_courses
WHERE macro_course = '$macro_course'
AND organization_id = (
SELECT id
FROM organizations
WHERE organization = '$organization'
AND city_id = (
SELECT id
FROM cities
WHERE city = '$city'
AND region_id = (
SELECT id
FROM regions
WHERE region = '$region' ))))) ORDER BY id DESC"; //just for me to know what query is being executed
if ($stmt = $this->mysqli->prepare(("
SELECT id, result, ip_address, added_date
FROM results
WHERE course_id = (
SELECT id
FROM courses
WHERE course = ?
AND macro_course_id = (
SELECT id
FROM macro_courses
WHERE macro_course = ?
AND organization_id = (
SELECT id
FROM organizations
WHERE organization = ?
AND city_id = (
SELECT id
FROM cities
WHERE city = ?
AND region_id = (
SELECT id
FROM regions
WHERE region = ? ))))) ORDER BY id DESC
"))) {
$return = array();
$stmt->bind_param('sssss', $course, $macro_course, $organization, $city, $region);
$stmt->execute();
if ($stmt->fetch()) {
$i = 0;
while ($row = $stmt->fetch()) {
print_r($row);//this is never reached
continue;
$s = new Result($row['result'], $row['added_date'], $row['id']);
$return[$i] = $s;
$i+=1;
}
}
}
return $return;
}
The problem is that this function returns 0 rows and 0 errors (checked with $this->mysqli->error), it seems that $row = $stmt->fetch() is always false.
However, if i copy and execute on PHPMyAdmin the output i get at the function top, i see
Showing lines 0 - 0 ( 1 total, Query time 0.0003 sec)
So the query returns a line but it is not catched by php. What am i missing? How can i fix this?
Because you used $stmt-fetch() two times here
if ($stmt->fetch()) {
$i = 0;
while ($row = $stmt->fetch()) {
Remove the if ($stmt->fetch()) condition, it will work as expected.
EDIT
from docs
Note that all columns must be bound by the application before calling $stmt->fetch().
You have to bind the result before calling $stmt->fetch() like this
/* bind result variables */
$stmt->bind_result($name, $code);

Categories