PHP Ranking and updating all database rows - php

Trying to rank the rows in my table and then update a field in each row with its rank number. The ranking will be based on a field with a points value.
The database structure is as follows:
Table name: blogs
fields: ID, buildpointsNow, build_rank
I want to run a cron job that will rank each row depending on its buildpointsNow value and then update its build_rank with that rank number.
So far i have tried:
UPDATE blogs
JOIN (SELECT p.id,
#curRank := #curRank + 1 AS rank
FROM blogs p
JOIN (SELECT #curRank := 0) r
ORDER BY p.buildpointsNow DESC
) ranks ON (ranks.id = blogs.id)
SET blogs.build_rank = blogs.build_rank;
And also:
update blogs cross join
(select #rn := 0) vars
set build_rank = (#rn := #rn + 1);
order by buildpointsNow;
Both of these throw no errors and do update the database rows. However they do not order the builds rank depending on the buildpointsNow field. They instead update each row in its order of creation / its ID.
Any ideas?

blogs need to be ordered by buildpointsNow before adding #curRank:
update blogs
join (
select p.id, #curRank := #curRank + 1 as rank
from (select id from blogs order by buildpointsNow) p
join (select #curRank := 0) r) ranks on ranks.id = blogs.id
set blogs.build_rank = ranks.rank;
Demo

Create a separate table and store ranking order there. You need a column with post_id and one with score. Every time you add/subtract points from score modify that column. And when you need to display the posts in ranking order, just sort that second lighter table table and join the posts heavier table.
Also make sure you index the score column.

Related

How to get rank position from MySQL SELECT statement

I'm trying to get the rank value of a MySQL SELECT statement, (MySQL is not something I'm too familiar with).
This query give me the correct results I am looking for in the correct order (by greater number of stats), but I need to get a particular value from the results.
SELECT id, stats,
#curRank := #curRank + 1 AS rank
FROM statistics.web_stats p, (SELECT #curRank := 0) r
ORDER BY stats DESC;
Gives me this expected result:
id,stats,rank
999,291,1
1137,82,2
1084,79,3
1111,60,4
1097,55,5
1094,51,6
1109,50,7
1112,49,8
1154,44,9
1082,36,10
What I need to do it get the rank value of any particular id, for example, in my PHP code, how would I find the rank position of id 1111 (to return the rank value of '4')?
I'm stuck with hoe to further extract values from the results. Do I need to save them somehow, or can I further expand the MySQL query?
Thanks.
You can use any one of the solutions:
You need to use a subquery to maintain rank position.
This will give you a result whose rank is 4:
SELECT *
FROM
(
SELECT id, stats,
#curRank := #curRank + 1 AS rank
FROM statistics.web_stats p, (SELECT #curRank := 0) r
ORDER BY stats DESC
) AS stat
WHERE rank = 4;
You can even use LIMIT OFFSET to query as they are already in order:
SELECT id, stats,
#curRank := #curRank + 1 AS rank
FROM statistics.web_stats p, (SELECT #curRank := 0) r
ORDER BY stats DESC
LIMIT 4, 1

How to make a table with the result of calculated rankings?

I'd like to make new table with the result of calculated rankings from a table. I work with PHP and MySQL.
I got some codes from googling and it works on the screen.
Select User_Id, Score, #rank := #rank + 1 as Ranking
from Rankings, (select #rank := 0) XX
order by Score desc
I'd like to know how to create new table with these data, so that I can see the rankings anytime I want.
And I wonder if this code is good for big data (lots of records).
Can anyone help this beginner? Thanks in advance for any help.
1: CREATE TABLE ... SELECT Syntax: You can create one table from another by adding a SELECT statement at the end of the CREATE TABLE statement.
CREATE TABLE new_table_name AS
SELECT User_Id, Score, #rank := #rank + 1 AS Ranking
FROM Rankings, (SELECT #rank := 0) XX
ORDER BY Score DESC;
Note: This will auto-detect column datatype and column names based on the select query and sometimes they are not proper.
To create desired column names and their data types, you can mention the same in CREATE TABLE clause.
CREATE TABLE new_table_name (user_id INT NOT NULL, rank INT)
SELECT User_Id, Score, #rank := #rank + 1 AS Ranking
FROM Rankings, (SELECT #rank := 0) XX
ORDER BY Score DESC;
2: INSERT ... SELECT Syntax: This will be used to store data of a select statement in the existing table.
INSERT INTO existing_table_name (user_id, rank)
SELECT User_Id, Score, #rank := #rank + 1 AS Ranking
FROM Rankings, (SELECT #rank := 0) XX
ORDER BY Score DESC;
According to this and this, you can use the CREATE TABLE ... SELECT syntax.
CREATE TABLE `UserRankings` AS SELECT User_Id, Score, #rank := #rank + 1 AS Ranking
FROM Rankings, (SELECT #rank := 0) XX
ORDER BY Score DESC
You can create a new table based on select query Data by using the following syntax
CREATE TABLE new_tbl [AS] select query;
Based on your query
Create table Tablename AS Select User_Id, Score, #rank := #rank + 1 as Ranking
from Rankings, (select #rank := 0) XX
order by Score desc
For more information refer https://dev.mysql.com/doc/refman/5.6/en/create-table-select.html

why positions not woking sql

My code below works fine but it does not print the result in descending order of overall marks. It rather arranges it in order of the student ID.
I have the code that arranges the students position. It works for one year value but when there are more than one year to account for, it does not print the result in descending order...
Below is the code that joins the marks table to the student table:
SELECT * FROM (
SELECT student_id, term, academic_year, classform_name, #prev:=#cur, #cur:=overall, #curRank := IF(#prev= #cur, #curRank, #curRank + #i ) AS classPosition, IF(#prev<> overall, #i:=1, #i:=#i+1) AS counter
FROM (SELECT m.*, SUM(total_marks) AS overall
FROM marks m
WHERE classform_name = ? AND term = ? AND academic_year = ?
GROUP BY m.student_id
ORDER BY overall DESC
) AS n
CROSS JOIN (SELECT #i:=0, #curRank := 0, #prev:=NULL, #cur:=NULL ) AS q
) AS completeRankings
JOIN studentstable ON completeRankings.student_id=studentstable.student_id ;
I've used JavaScript dataTables to solve it. I reorder the records from highest score to lowest

Get the rank of the row given the order in sql

Let's say I have two tables like the following:
user_id
1
2
3
post_id user_id
1 2
2 3
3 2
The first table has all of the user information and the second table is a list of posts from users.
With these table, I want to make a ranking of who post the most posts. To do this, I can use the following sql
select user.user_id from user
left join post on user.user_id=post.user_id
order by count(post.post_id)
which will give me
user_id
2
3
1
, but what if I only want a single user's rank? In other words, I want to write a sql statement that will return what place the user is in given the user_id. For example, I want 1 as output if I have user_id of 2, 2 as the output if I have user_id 3, and 3 as the output if I have user_id 1.
Is this possible, or would I have to select the entire table and do a while loop in php until I hit the user and count the rows above?
Unfortunately, for a single user's rank, you pretty much have to calculate the rank of everyone and then pull out the single user. So, the ranking for all users is:
select u.user_id, count(p.post_id), (#rn := #rn + 1) as ranking
from user u left join
post p
on u.user_id = p.user_id cross join
(select #rn := 0) params
group by u.user_id
order by count(p.post_id) desc;
And for one user, use a subquery:
select *
from (select u.user_id, count(p.post_id), (#rn := #rn + 1) as ranking
from user u left join
post p
on u.user_id = p.user_id cross join
(select #rn := 0) params
order by count(p.post_id) desc
) u
where u.user_id = $USERID;
You can use user-defined variables for this:
select rnk
from (
select user.user_id, #rnk:#rnk+1 rnk
from user
left join post on user.user_id=post.user_id
cross join (select #rnk:=0) t
group by user.user_id
order by count(post.post_id) desc
) t
where user_id = ?
BTW -- I believe your query was missing a group by clause. Added above.

Ranking mysql and query for one people

I use this script for my ranking. But I'm not good in MYSQL so maybe someone can help me to change this script to add to this variable:
WHERE id = '$id'
This is what i use:
SELECT id,punkty,
#curRank := #curRank + 1 AS rank
FROM users p, (SELECT #curRank := 0) r
ORDER BY punkty DESC;
I dont know how I can change this script to check one id ? (where id = '$id')
As from comments what i understand the rank given by your query against each user,now you want to know the rank for a given user. You can get the desired rank for the given user's id by doing a sub select
SELECT * FROM (
SELECT id,punkty,
#curRank := #curRank + 1 AS rank
FROM users p, (SELECT #curRank := 0) r
ORDER BY punkty DESC
) t
WHERE id='6';
In below demo if you see the second result set,it shows all the users with their rank and the first query is for one user with id = 6 and his rank is 4 according to the result set of second query
Demo

Categories