I have the following code it works well, except that I cannot filter to get a specific position of a single student. I shows all students yet I just want to be able to filter and get the position of a specific child.
SELECT users.name,users.lastname, assessement_progress_reports.student_average as avg,
(#rank_count := if((#rn := (#rn + 1)) > 0,
if((assessement_progress_reports.student_average < #prev_value),
#rn,
#rank_count), NULL)
) as rank,
#prev_value := assessement_progress_reports.student_average avg
FROM assessement_progress_reports CROSS JOIN
(SELECT #prev_value := NULL, #rank_count := 1, #rn := 0) init INNER JOIN users on users.id=assessement_progress_reports.student_id where assessement_progress_reports.assessement_id=2 and assessement_progress_reports.student_stream=1 ORDER BY avg DESC
Related
I am little new to sql and I need to rank my votes table based on votes assigned to each person and rank should be same for the similar votes.
My table would be like
CREATE TABLE votes ( name varchar(10), votes INT );
INSERT INTO votes VALUES
('Ann',100), ('Jones',151), ('Smith',100), ('Rose',240), ('Lee',500), ('Adhams',500);
In my display rows I need to have the rank column first and it should display the rank based on the highest number of votes. Importantly same number of votes need to have the same rank.
I have tried it several times and failed to do it...
Please help me
thanks
You can try below code. There are many links available which would be easily find your answer if you have carefully searched.
SET #rank=0;
SET #votes=0;
select x.rank as rank, x.name as name, x.votes as votes
from(
select #rank:=if(#votes=votes,#rank, #rank +1)AS rank,
#votes := votes,
v.name,
v.votes
from votes v
order by v.votes desc) as x;
To generate RANK, you first need a row number in the order of decreasing votes (variable #rn) and then based on the previous value of vote, create rank (variable #rank).
Try this:
SELECT v.*,
#rank := if((#rn := #rn + 1) is not null,
if (#votes = votes,
#rank,
if ((#votes := votes) is not null, #rn, 1)
),1
) rank
FROM votes v
CROSS JOIN (
SELECT
#votes := NULL,
#rank := 0,
#rn := 0
) t
ORDER BY v.votes DESC;
Demo
About this:
(#rn := #rn + 1) is not null
Since, the expression #rn := #rn + 1 can't be null, we use it to our advantage by not duplicating the whole logic twice.
You can use variables for this:
SELECT #rnk := IF(#v = votes, #rnk,
IF(#v := votes, #rnk + 1, #rnk + 1) AS rnk
name, votes
FROM mytable
CROSS JOIN (SELECT #rnk := 0, #v = :0) AS vars
ORDER BY votes DESC
I have a query that loops through each result and updates a column:
SET #counter = 0;
UPDATE users SET rank_level = #counter := #counter + 1 ORDER BY level DESC;
SELECT rank_level, level FROM users ORDER BY rank_level ASC;
Which outputs:
But what I am trying to do is only increment the variable if the level value changes. So where the two rows that have the same level are, they would have the same rank of 8 too.
Any ideas? Thanks.
rank() is a bit tricky in MySQL. One way is with a correlated subquery:
select u.*,
(select count(*) + 1
from users u2
where u2.level < u.level
) as rank
from users u;
This is tricky to put into an update. Assuming you have a userId column, you can use join:
update users u join
(select u.*,
(select count(*) + 1
from users u2
where u2.level < u.level
) as rank
from users u
) ur
on u.userId = ur.userId
set rank_level = rank;
Doing a rank with variables is rather tricky (row_number() and dense_rank() are easier), because it requires three variables. Here is the select version:
select u.*,
(#r := if(#l = level,
if(#rn := #rn + 1, #r, #r)
if(#l := level,
#rn := #rn + 1, #rn := #rn + 1
)
)
) as ranking
from users u cross join
(select #l := -1, #rn : = 0, #r := 0) params
order by level;
So in the end I went with this:
SET #prev_value = NULL;
SET #rank_count = 0;
UPDATE users SET rank_level = CASE
WHEN #prev_value = level THEN #rank_count
WHEN #prev_value := level THEN #rank_count := #rank_count + 1
END
ORDER BY level DESC;
Based on this answer: Rank function in MySQL
I have a table with entries names,date etc.
select name from names
order by names
for example.
I need an output like
1|paul
2|paul
1|morne
1|marone
2|marone
3|marone
i have no clue where to start to do a count like this for when i grou i cant get this right.
In MySQL, the easiest way to do this is with variables:
select n.name,
(#rn := if(#name = name, #rn + 1, 1)) as seqnum,
#name := name
from names n cross join
(select #name := '', #rn := 0) var
order by names;
EDIT:
In case anyone comes across this answer, the above sort-of works, but MySQL does not guarantee the order of evaluation of expressions. So, I now write the above as:
select n.name,
(#rn := if(#name = name, #rn + 1,
if(#name := name, 1, 1)
)
) as seqnum
from names n cross join
(select #name := '', #rn := 0) var
order by names;
Because all the variable assignments are in one statement, there is no problem with the order of evaluation of expressions in the select statement.
I've been playing with this SQL code:
SELECT
id,
#prev := #curr as prev,
#curr := measure as curr,
#rank := IF(#prev > #curr, #rank+#ties, #rank) AS rank,
#ties := IF(#prev = #curr, #ties+1, 1) AS ties,
(1-#rank/#total) as percentrank
FROM
mytable,
(SELECT
#curr := null,
#prev := null,
#rank := 0,
#ties := 1,
#total := count(*) from mytable where measure is not null
) b
WHERE
measure is not null
ORDER BY
measure DESC
I'd like to write the calculated 'percentrank' back to each corresponding row of mytable in a column named "percentile," but I can't recall how to work in my update statement.
I appreciate the help.
Credit to http://code.openark.org/blog/mysql/sql-ranking-without-self-join for the SQL.
To update from a subquery, give the subquery an alias so that it's a derived table. Then use this syntax:
update YourTable
set SomeField = DerivedTable.something
, etc
from YourTable join
(subquery goes here) DerivedTable on YourTable.Whatever = DerivedTable.Whatever
etc
I have a table which has the following two columns including others: rating, price and code. Ratings is similar to a category. I wish to generate the top 10 for each rating order by price ascending where code = 'ABC'. I'm at a loss to figure out where to put the last two conditions in the following mysql statement. Please can someone advise. Many thanks
SELECT x.*
FROM (SELECT t.*,
CASE
WHEN #rating != t.rating THEN #rownum := 1
ELSE #rownum := #rownum + 1
END AS rank,
#rating := t.rating AS var_rating
FROM offers t
JOIN (SELECT #rownum := NULL, #rating := '') r
ORDER BY t.rating) x
WHERE x.rank <= 10
ALso, what if the rating column had entries like 1, 1, 1k, 1*, 1+, 2, 2, 2+, 3,3,3* etc, how would I be able to consider all of these entries as '1', 2 and 3 respectively in the same sql statement?
Try this:
SELECT x.*
FROM (SELECT t.*,
CASE
WHEN #rating != t.rating THEN #rownum := 1
ELSE #rownum := #rownum + 1
END AS rank,
#rating := t.rating AS var_rating
FROM offers t
JOIN (SELECT #rownum := NULL, #rating := '') r
WHERE code = 'ABC'
ORDER BY t.rating, price) x
WHERE x.rank <= 10
The changes are:
Added a WHERE clause after the JOIN clause
Added price to the ORDER BY clause.