I am trying to generate row number for each row selected from my database but it seems that the row number follows the sequence of the table before it's arranged (order by).
Actual table
https://www.dropbox.com/s/otstzak20yxcgt6/test1.PNG?dl=0
After query
https://www.dropbox.com/s/i9jaoy04vq6u2zh/test2.PNG?dl=0
Code
SET #row_num = 0;
SELECT #row_num := #row_num + 1 as Position, Student.Stud_ID, Student.Stud_Name, Student.Stud_Class, SUM(Grade.Percentage) AS Points
FROM Student, Student_Subject, Grade
WHERE Student.Stud_ID = Student_Subject.Stud_ID
AND Student_Subject.Stud_Subj_ID = Grade.Stud_Subj_ID
AND Student.Stud_Form = '1'
AND Grade.Quarter = '1'
GROUP BY Student.Stud_ID
ORDER BY Points DESC
Pls help. Looking forward to receiving replies from yall. Thanks!
Try an inner select, so the row number will be generated after the ORDER BY like so:
SET #row_num = 0;
SELECT #row_num := #row_num + 1 as Position, s.*
FROM
(
SELECT
Student.Stud_ID, Student.Stud_Name, Student.Stud_Class, SUM(Grade.Percentage) AS Points
FROM Student, Student_Subject, Grade
WHERE Student.Stud_ID = Student_Subject.Stud_ID
AND Student_Subject.Stud_Subj_ID = Grade.Stud_Subj_ID
AND Student.Stud_Form = '1'
AND Grade.Quarter = '1'
GROUP BY Student.Stud_ID
ORDER BY Points DESC
) AS s;
Related
I have a users table with phase1 and phase2 columns that i need to calculate the users rank in each phase and store it in these fields.
the ranking is calculated based on a different table points where i have the points by phase for each user.
what i am trying to do is
sum all points for each user by phase and calculate his rank based on that
in case the user points are equal compare the sum of grade1 in case that is also equal compare the sum of grade2
update users table with his rank in each phase
here is how my new table look like with some demo data
sql fiddle demo
currently I use the below code to calculate the ranking from my old table where both rank and user info are in the same table
old sql fiddle demo
update users a
join (
select id,
(
select count(distinct total)
from users d
where c.total < d.total
) +1 rank
from users c
) b on a.id = b.id
set a.rank = b.rank
there are analytics function in oracle called as rank() and dense_rank() which can be useful to get your result.
As you are using mysql, I tried to convert those function in mysql equivalent.
You can get the desired result with following query which you can use to update users table. You may have to change it further if for the logic when there is tie on grades as well.
set #pk1 ='';
set #rn1 =1;
set #tot ='';
set #val =1;
SELECT id,
name,
phase,
phasetotal,
denseRank
FROM
(
SELECT id,
name,
phase,
phasetotal,
#rn1 := if(#pk1=phase, #rn1+#val,1) as denseRank,
#val := if(#pk1=phase, if(#tot=phasetotal, #val+1, 1),1) as value,
#pk1 := phase,
#tot := phasetotal
FROM
(
select users.id,users.name, points.phase, sum(points.points)
as phasetotal from users,points where users.id = points.userid
group by users.id, points.phase order by points.phase, phasetotal desc, points.grade1 desc, points.grade2 desc
) A
) B;
Here's the update query
set #pk1 ='';
set #rn1 =1;
set #tot ='';
set #val =1;
UPDATE users u join (
SELECT id,
name,
phase,
phasetotal,
denseRank
FROM
(
SELECT id,
name,
phase,
phasetotal,
#rn1 := if(#pk1=phase, #rn1+#val,1) as denseRank,
#val := if(#pk1=phase, if(#tot=phasetotal, #val+1, 1),1) as value,
#pk1 := phase,
#tot := phasetotal
FROM
(
select users.id,users.name, points.phase, sum(points.points)
as phasetotal from users,points where users.id = points.userid
group by users.id, points.phase order by points.phase, phasetotal desc, points.grade1 desc, points.grade2 desc
) A
) B ) C on u.id = C.id
SET u.phase1 = CASE WHEN C.phase = 1 and u.phase1 = 0 THEN C.denseRank ELSE u.phase1 END,
u.phase2 = CASE WHEN C.phase = 2 and u.phase2 = 0 THEN C.denseRank ELSE u.phase2 END;
Output: https://www.dropbox.com/s/q9bjrzndbzj0l2i/test3.PNG?dl=0
How do I incorporate a query into the current code if I want to get only the Position (row_number) = 3 if lets say the Stud_ID = 4?
SET #row_num = 0;
SELECT #row_num := #row_num + 1 as Position, s.*
FROM
(
SELECT
Student.Stud_ID, Student.Stud_Name, Student.Stud_Class, SUM(Grade.Percentage) AS Points
FROM Student, Student_Subject, Grade
WHERE Student.Stud_ID = Student_Subject.Stud_ID
AND Student_Subject.Stud_Subj_ID = Grade.Stud_Subj_ID
AND Student.Stud_Form = '1'
AND Grade.Quarter = '1'
GROUP BY Student.Stud_ID
ORDER BY Points DESC
) AS s;
Thanks!!
Use a subselect over your query and filter it with your desired row number
SELECT *
FROM (
SELECT #row_num := #row_num + 1 AS `Position`, s.*
FROM
(
SELECT
Student.Stud_ID, Student.Stud_Name, Student.Stud_Class, SUM(Grade.Percentage) AS Points
FROM Student, Student_Subject, Grade
WHERE Student.Stud_ID = Student_Subject.Stud_ID
AND Student_Subject.Stud_Subj_ID = Grade.Stud_Subj_ID
AND Student.Stud_Form = '1'
AND Grade.Quarter = '1'
GROUP BY Student.Stud_ID
ORDER BY Points DESC
) AS s
CROSS JOIN (SELECT #row_num := 0) AS s1
) AS t
WHERE t.Position = 3
I have table with id (store user id) and score in different match. I want what is the position of a user.
So for i try this sql fiddle;
in this I am getting all the row but I need only user having id 3 and it position in the table.
like this:
Score Postion
26 3
Even i try to do like this but no success
MySql: Find row number of specific record
With MySQL, how can I generate a column containing the record index in a table?
I got the answer: http://sqlfiddle.com/#!2/b787a/2
select * from (
select T.*,(#rownum := #rownum + 1) as rownum from (
select sum(score) as S,id from mytable group by id order by S desc ) as T
JOIN (SELECT #rownum := 0) r
) as w where id = 3
Updated sqlfiddle and above query. Now it is working perfectly.
I think this should do the trick:
SELECT totalScore, rownum FROM (
SELECT id,sum(score) AS totalScore,(#rownum := #rownum + 1) AS rownum
FROM mytable
JOIN (SELECT #rownum := 0) r
group by id) result
WHERE result.ID = 3;
just add a where clause
select x.id,x.sum,x.rownum
from(
select id,sum(score) as sum,(#rownum := #rownum + 1) as rownum
from mytable
JOIN (SELECT #rownum := 0) r
group by id
) x
where id =3
I'm ordering a recordset like this:
SELECT * FROM leaderboards ORDER BY time ASC, percent DESC
Say I have the id of the record which relates to you, how can I find out what position it is in the recordset, as ordered above?
I understand if it was just ordered by say 'time' I could
SELECT count from table where time < your_id
But having 2 ORDER BYs has confused me.
You can use a variable to assign a counter:
SELECT *, #ctr := #ctr + 1 AS RowNumber
FROM leaderboards, (SELECT #ctr := 0) c
ORDER BY time ASC, percent DESC
Does this do what you want?
SELECT count(*)
FROM leaderboards lb cross join
(select * from leaderboards where id = MYID) theone
WHERE lb.time < theone.time or
(lb.time = theone.time and lb.percent >= theone.percent);
This assumes that there are no duplicates for time, percent.
I have a table
scores(user, score)
and I have this query
SET #row_num = 0;
SELECT #row_num := #row_num + 1 as row_index, user, score
FROM scores ORDER BY score DESC
now I want to select, from this query result, the user with name 'john' and score '1400' to know what is his row_index, something like
SELECT row_index
FROM *result* WHERE user='john' AND score=1400
how do I do that? I tried
SET #row_num = 0;
SELECT row_index
FROM (SELECT #row_num := #row_num + 1 as row_index, user, score
FROM scores ORDER BY score DESC)
WHERE user='john' AND score=1400`
but phpMyAdmin says
#1248 - Every derived table must have its own alias
How can I do that?
Thank you,
Alessandro
You haven't added an alias to the derived table.
SELECT row_index FROM (...) AS alias
WHERE alias.user = 'john' AND alias.score = 1400
Query:
SET #row_num = 0;
SELECT a.row_index
FROM (SELECT #row_num := #row_num + 1 as row_index,
user,
score
FROM scores ) a
WHERE a.user='john' AND a.score=1400
ORDER BY a.score DESC
I think Ordering in Subquery not always allowed.
Try to use views.
SET #row_num = 0;
CREATE VIEW v AS SELECT #row_num := #row_num + 1 as row_index, user, score FROM scores ORDER BY score DESC;
SELECT row_index FROM v;
Try this:
SET #row_num = 0;
SELECT row_index FROM (SELECT #row_num := #row_num + 1 as row_index, user,
score FROM scores ORDER BY score DESC) AS alias1 WHERE user='john' AND score=1400