Mysql - order by 2 ranks - mysql

I have a table of items. item has id, score 1, score 2.
I want to select 12 known items (using WHERE id IN (....)) and order them by a score that is the sum of score1 and score2's ranks. rank is the location of the score if the 12 items were ordered by it.
How can I do this in mysql?
Edit:
After 4 answers I see that the solution is probably more complicated than I expected. so let me ask the question in another way.
If I use select *, [calculation] from table where id IN (odered list of ids). Can I somehow use the position of each id in the original ordered list of ids in [calculation]?

Out of my head:
CREATE TEMPORARY TABLE t_1(score_1_rank INT AUTO_INCREMENT, id)
CREATE TEMPORARY TABLE t_2(score_2_rank INT AUTO_INCREMENT, id)
INSERT INTO t_1(id)
SELECT id
FROM items i
WHERE id IN ()
ORDER BY score_1
INSERT INTO t_2(id)
SELECT id
FROM items i
WHERE id IN ()
ORDER BY score_2
SELECT ...
FROM items i
INNER JOIN t_1 t1
ON t1.id = i.id
INNER JOIN t_2 t2
ON t2.id = i.id
ORDER BY t1.rank + t2.rank
Did I understand your request correctly?

Is this what you are looking to do?
SELECT
(CAST(score1 AS INT) + CAST(score2 AS INT)) AS rank
FROM items
WHERE id IN(...)
ORDER BY rank DESC

SELECT id, score1, score2,
r1.rank AS rank1,
r2.rank AS rank2,
(r1.rank + r2.rank) rankSum
FROM items i
INNER JOIN (
SELECT #rank := #rank + 1 AS rank, id
FROM items, (SELECT #rank :=0) AS r
ORDER BY score1
) AS r1 ON r1.id = i.id
INNER JOIN (
SELECT #rank := #rank + 1 AS rank, id
FROM items, (SELECT #rank :=0) AS r
ORDER BY score2
) AS r2 ON r2.id = i.id
ORDER BY rankSum
But I doubt that this will be somehow very efficient, not only because the query cannot make use of the query cache.

Related

MySQL row number with ORDER BY

Right now I have this:
SELECT
#rownum := #rownum + 1 AS rownum,
T1.*
FROM
(
SELECT user.username, points
FROM scores
JOIN users AS user ON user.id = scores.user_id
) AS T1, (SELECT #rownum := 0) AS r
ORDER BY T1.points DESC, rownum ASC
And this returns usernames, points and row number. Points are ordered but row numbers are all messed up. If I put ORDER BY into the nested select then row nubmers are ordered but points are not. So what I need to change so that I get points ordered in descending order and row number would be in ascending, what I wanna create is leaderboards, so that user whit most point is first etc.
It looks like you need your rownum to be paired up with points that have been pre-ordered. Hence you need to move ORDER BY on points into the nested select:
SELECT
#rownum := #rownum + 1 AS rownum,
T1.*
FROM
(
SELECT user.username, points
FROM scores
JOIN users AS user ON user.id = scores.user_id
ORDER BY points DESC
) AS T1, (SELECT #rownum := 0) AS r
ORDER BY rownum ASC
Does this do what you want?
SELECT (#rownum := #rownum + 1) AS rownum,
us.*
FROM (SELECT u.username, s.points
FROM scores s JOIN
users u
ON u.id = s.user_id
ORDER BY s.points DESC
) us CROSS JOIN
(SELECT #rownum := 0) params;
Basically, this just leaves the ordering in the subquery.
If points is not a number, then use ORDER BY (s.points + 0) DESC in the subquery. Or fix the data so it is stored as a number.

Php Mysql Student Rank

I have this data in my database, all i want to do is to get the rank position and ties of student in a class based on the there total score , subject, session and term
i tried this but getting different position
SELECT d.username, c.ranks FROM
( SELECT total_score, #rank:=#rank+1 Ranks FROM
(SELECT DISTINCT total_score FROM
cbt_result a ORDER BY total_score DESC) t,
(SELECT #rank:= 0) r )
c INNER JOIN cbt_result d
ON c.total_score = d.total_score
WHERE term = 'first'
AND class_id ='$key'
AND subject_id = '$subkey'
AND username ='$student_username'
AND session_term = '$session_term_key'

Selecting last 5 positions of all users from a join

I have 2 tables: player_positions (records the gps coordinates of all players) and players (records data for each player).
players
player_id, player_name
player_positions
player_id, player_lat, player_lon, timestamp
I want to get last 5 positions for all players.
My first query for selecting the last locations of one player is:
SELECT * FROM player_positions WHERE player_id = 1 ORDER BY timestamp DESC LIMIT 5
But I don't know how to duplicate this query to extract all players data. I believe I have to do a select within a previous join but not sure how to write it.
Thank you.
You can emulate the rownumber function found in other dbs like so, to solve this problem.
SELECT
player_id,
player_lat,
player_lon,
`timestamp`
FROM
(SELECT
pp.player_id,
pp.player_lat,
pp.player_lon,
pp.`timestamp`,
#rn := if(#prev = pp.player_id, #rn + 1,1) as rn,
#prev:=pp.player_id
FROM
Player_Positions as pp
JOIN (SELECT #Prev:= Null, #Rn := 0) as v
ORDER BY
pp.player_id,
pp.timestamp desc) as t
WHERE
rn <= 5;
Note that if for some reason there's a tie for 5th the database will arbitrarily pick one. Since it's unlikely that a player can be in two positions for the same timestamp you should be okay.
Try this :
SELECT pp.* , p.player_name
FROM player_positions pp
INNER JOIN players p ON p.player_id = pp.player_id
GROUP BY pp.player_id
ORDER BY pp.timestamp DESC LIMIT 5
EDIT:
SELECT pp.* , p.player_name
FROM player_positions pp
INNER JOIN players p ON p.player_id = pp.player_id
LEFT OUTER JOIN player_positions pp2 ON pp.player_id = pp2.player_id AND pp.timestamp < pp2.timestamp
GROUP BY pp.player_id
HAVING COUNT(*) < 5
ORDER BY pp.timestamp DESC LIMIT 5

MySQL - Rank COUNT from GROUP BY returning nil

I'm trying to follow this example: MySQL - ranking by count() and GROUP BY but my rank column keeps returning nil.
Here's my query:
SELECT
#rownum := #rownum+1 AS rank,
q.id,
q.Name,
q.count
FROM
(SELECT
Accounts.id,
Accounts.Name,
COUNT(Accounts.Name) AS count
FROM
player_to_team_histories
INNER JOIN
team_histories ON team_histories.id = player_to_team_histories.team_history_id
INNER JOIN
teams ON teams.id = team_histories.team_id
INNER JOIN
accounts ON accounts.id = teams.account_id
WHERE
accounts.AccountTypeId = 1 AND player_id IN (SELECT
player_id
FROM
player_to_team_histories
WHERE
player_to_team_histories.not_valid IS NULL AND team_history_id = (SELECT
team_history_id
FROM
player_to_team_histories
INNER JOIN
team_histories ON team_histories.id = player_to_team_histories.team_history_id
WHERE
player_to_team_histories.id = 574651))
GROUP BY Accounts.Name
ORDER BY count DESC)q
Every column except rank is returning as expected, and rank is returning null for every row.
You have to initialize your rownum to 0 before starting to increment it, either by
SET #rownum := 0;
before the query, or by a separate SELECT clause after your first FROM:
SELECT ...
FROM
(SELECT #rownum := 0 ) counter,
(SELECT
... )

Rank not being determined properly

I'm using this query:
SELECT A.place_idx,A.place_id,B.TOTAL_CNT,(#r := #r + 1) AS rank FROM CUSTOM_LIST
AS A
INNER JOIN
(SELECT #r := 0)
AS C
INNER JOIN
(SELECT place_id,COUNT(place_id) AS TOTAL_CNT from COUNT_TABLE GROUP BY place_id)
AS B ON B.place_id=A.place_id order by B.TOTAL_CNT desc;
Which gives this result:
But I want this result:
How do I need to modify my query? What am I doing wrong?
SELECT *,(#r := #r + 1) AS rank FROM
(
SELECT A.place_idx,A.place_id,B.TOTAL_CNT FROM CUSTOM_LIST
AS A
INNER JOIN
(SELECT place_id,COUNT(place_id) AS TOTAL_CNT from COUNT_TABLE GROUP BY place_id)
AS B ON B.place_id=A.place_id order by B.TOTAL_CNT desc
) AS T, (SELECT #r := 0) AS tt
Your C.rank is getting calculated as they are processed, not after they are sorted. There is really no need for this data, anyways. Since you're sorting the rows by your metric, you know the first row is the first rank, etc. You can handle it on the programming side of things after you pull it out.
Alternatively, you can put what you have in an inner select, then do the rank after.