I have a high scores table that is slightly more complicated because scores are tracked in rounds (round 1, round 2, round 3, etc.). Sample table:
scoreID
roundID
userID
score
1
1
2
25
2
1
3
12
3
1
4
14
4
1
5
6
5
2
2
39
6
2
3
23
7
2
4
13
8
2
5
26
There can be many more rounds, and many more users.
I would like to pull the top 3 user scores from each round. My select statement at the moment looks like this:
select `scores`.`score`, `users`.`username`, `scores`.`roundID`
FROM `scores`
INNER JOIN `users` on `users`.`user_id` = `scores`.`userID`
ORDER BY `scores`.`score` DESC LIMIT 3;
However, this returns a result like so:
score
username
roundID
39
joey
2
26
bubba
2
25
george
1
when what I want is the top 3 scores per round:
score
username
roundID
25
george
1
14
bubba
1
12
joey
1
39
george
2
26
homey
2
23
joey
2
How do I select the top 3 scores in each round so my result mirrors the table immediately above?
You would do this like:
select score, username, roundID
from (
select
score, userID, roundID,
rank() over (partition by roundID order by score desc) score_rank
from score
) ranked_scores
inner join users on users.user_id = ranked_scores.userID
where score_rank <= 3
order by roundID, score, username
Related
I have 2 tables.
MARKET TABLE
ID main_key sub_key name created_at
------------------------------------------------------
1 1 1 bottle 1606636000
2 2 1 flask 1606642546
3 2 2 flask 1606650045
4 3 1 can 1606650445
5 3 2 can 1606651546
6 4 1 glass 1606652545
MARKET_UPDATES TABLE
ID main_key sub_key price update
------------------------------------------------------
1 1 1 100 1606665555
2 2 1 120 1606665555
3 2 2 150 1606665555
4 3 1 500 1606665555
5 3 2 550 1606665555
6 4 1 25 1606665555
7 1 1 110 1606665666
8 2 1 135 1606665666
9 2 2 145 1606665666
10 3 1 490 1606665666
11 3 2 440 1606665666
12 4 1 29 1606665666
I've tried this.
SELECT *
FROM market m
JOIN (
SELECT MAX(id) max_id, fk_main_key
FROM market_update
GROUP BY fk_main_key, sub_key
) m_max ON (m_max.fk_main_key = m.main_key)
JOIN market_update mu ON (mu.id = m_max.max_id)
But it multiples it a lot of times and I end up with a lot of the same lines. I think it multiples main_key amount and sub_key amount.
I am trying to JOIN MARKET_UPDATES into MARKET so I can get the latest prices from MARKET_UPDATES, but my issue is that I have 2 id's that I have to check on, main_key & sub_key.
So I have to merge the MARKET table with id(7-12) in MARKET_UPDATES.
here is one way based on your query :
SELECT *
FROM market m
JOIN (
SELECT MAX(id) max_id , fk_main_key, sub_key
FROM market_update
GROUP BY fk_main_key, sub_key
) m_max
ON (m_max.fk_main_key = m.main_key
and m_max.sub_key = m.sub_key)
JOIN market_update mu ON (mu.id = m_max.max_id)
and here is another way using window function RANK() :
SELECT *
FROM market m
JOIN (
SELECT id
, fk_main_key
, sub_key
, rank() over (partition by fk_main_key, sub_key order by id desc ) rnk
FROM market_updat
) mu
ON mu.fk_main_key = m.main_key
and mu.sub_key = m.sub_key
and rnk = 1
i have a table that looks like this:
ID GameID DateID Points Place
-------------------------------------
10 1 1 100 1
11 1 1 90 2
12 1 1 80 3
13 1 1 70 4
14 1 1 60 5
10 1 1 100 1
10 1 1 50 1
10 1 1 100 1
10 1 1 100 1
10 1 1 100 1
10 1 1 100 1
10 1 1 100 1
10 1 1 100 1
10 1 1 100 1
10 1 1 50 5
10 1 1 50 5
12 1 1 100 1
-------------------------------------
I want a table with two columns, one for the total points (summated scores/points) of one player and one for the id of the player. But for one player only ten scores may be counted, so for example if one player played thirteen times, only the ten highest scores are counted.
For the example above I want a table that looks like this:
ID totalPoints
-------------------
10 950
11 90
12 180
13 70
14 60
------------------
At the moment I tried this:
SELECT ID,
sum(Points) AS totalPoints
FROM (SELECT Points, ID
FROM Gamer
ORDER BY Points DESC LIMIT 10) AS totalPoints
ORDER BY Points DESC
but it limits the entries at all to ten and not to ten per player.
I hope anybody can help me :)
In all existing versions:
DELIMITER $
CREATE FUNCTION `totalPoints`(gamer_id INT) RETURNS int(11)
BEGIN
DECLARE s INT DEFAULT 0;
SELECT SUM(Points) INTO s FROM ( SELECT Points FROM Gamer WHERE ID=gamer_id ORDER BY Points DESC LIMIT 10) sq;
RETURN s;
END$
DELIMITER ;
SELECT DISTINCT ID, totalPoints(ID) FROM Gamer;
Alternative in MariaDB 10.2 (currently Beta), which has window functions:
SELECT ID, SUM(Points) FROM (
SELECT ID, Points, ROW_NUMBER()
OVER (PARTITION BY ID ORDER BY Points DESC) AS nm
FROM Gamer
) sq WHERE nm <= 10 GROUP BY ID;
I'm pretty sure there are other ways to do the same, these two are first that came to mind.
Imagine you have a members with distinct member_ids and dates of service
you now need to order the dates of service in ascending order and return the order of these dates in another column (date_count). the final result will look like this:
memberid name date date_count
122 matt 2/8/12 1
122 matt 3/9/13 2
122 matt 5/2/14 3
120 luke 11/15/11 1
120 luke 12/28/14 2
100 john 1/12/10 1
100 john 3/2/12 2
100 john 5/30/12 3
150 ore 5/8/14 1
150 ore 9/9/14 2
here is the query that works but does not return the date_count in ranking (1,2,3) order. This instead returns the same number for date_count, not sure why the num
memberid name date_count
122 matt 3
122 matt 3
122 matt 3
120 luke 5
120 luke 5
120 luke 5
100 john 6
100 john 6
150 ore 2
150 ore 2
SELECT A.MEMBERID, A.NAME,A.DATE, COUNT(B.DATE) AS DATE_COUNT FROM #WCV_COUNTS A
INNER JOIN #WCV_COUNTS B
ON A.MEMBERID <= B.MEMBERID
AND A.MEMBERID= B.MEMBERID
GROUP BY A.MEMBERID, A.NAME, A.DATE
ORDER BY A.MEMBERID
Thanks for help in advance!
Use ROW_NUMBER()
SELECT memberid, name, date,
ROW_NUMBER() OVER (PARTITION BY memberid ORDER BY date) AS date_count
FROM #WCV_COUNTS
ORDER BY memberid, date
I have three tables:
Students
-------------------------------------------------------------
studentId first last gender weight
-------------------------------------------------------------
1 John Doe m 185
2 John Doe2 m 130
3 John Doe3 m 250
Lifts
-------------------
liftId name
-------------------
1 Bench Press
2 Power Clean
3 Parallel Squat
4 Deadlift
5 Shoulder Press
StudentLifts
------------------------------------------------
studentLiftId studentId liftId weight
------------------------------------------------
1 1 1 185
2 2 3 130
3 3 1 190
4 1 2 120
5 2 1 155
6 3 2 145
7 1 1 135
8 1 1 205
9 2 3 200
10 1 3 150
11 2 2 110
12 3 3 250
I would like to have four top lists:
Bench Press
Parallel Squat
Power Clean
Total of the above 3
I can successfully grab a top list for each specific lift using the following query:
SELECT s.studentId, s.first, s.last, s.gender, s.weight, l.name, sl.weight
FROM Students s
LEFT JOIN (
SELECT *
FROM StudentLifts
ORDER BY weight DESC
) sl ON sl.studentId = s.studentId
LEFT JOIN Lifts l ON l.liftId = sl.liftId
WHERE l.name = 'Bench Press'
AND s.gender = 'm'
AND s.weight > 170
GROUP BY s.studentId
ORDER BY sl.weight DESC
However, I am stuck on how to add the highest total of each lift for each student. How can I first find the highest total for each student in each lift, and then add them up to get a total of all three lifts?
Edit
The result set that I am looking for would be something like:
-------------------------------------------------
studentId first last weight
-------------------------------------------------
3 John Doe3 585
1 John Doe 475
2 John Doe2 465
I also forgot to mention that I would actually like two lists, one for students above 170 and one for students below 170.
SELECT -- join student a total weight to the student table
A.studentId,
A.first,
A.last,
C.totalWeight
FROM
Student A,
(
SELECT -- for each studet add the max weights
sum(B.maxWeight) as totalWeight,
B.studentID
FROM (
SELECT -- for each (student,lift) select the max weight
max(weight) as maxWeight,
studentId,
liftID
FROM
StudentLifts
GROUP BY
studentId,
liftID
) B
GROUP BY
studentId
) C
WHERE
A.studentID = C.studentId
-- AND A.weight >= 170
-- AND A.weight < 170
-- pick one here to generate on of the two lists.
If my Data is
Name - playerID - matchID - Innings - Runs
James 1 1 1 5
James 1 1 2 8
Darren 2 1 1 3
Darren 2 1 2 9
James 1 2 1 10
James 1 2 2 12
Darren 2 2 1 13
Darren 2 2 2 19
and my sql data is
$query = "SELECT playerID, name,
SUM(runs) AS runs_scored,
MAX(runs) AS highest_score
FROM matchPlayer GROUP BY playerID";
Then the output would read
James has scored 35 runs with a highest score of 18
Darren has scored 44 runs with a highest score of 19
Now I wish to get the highest total scored in one match (that is combining innings 1 & 2)?
I have no idea how to start on this query :(
EDIT
The exact info I require is the HIGHEST match total, so James has 13 combined runs from matchID 1 and 22 combined runs from matchID 2 - so the answer I am after is 22.
You need to do it in two stages:
SELECT ms.playerID, mp.name, SUM(ms.runs_by_match) AS runs_scored,
MAX(ms.runs_by_match) as highest_score
FROM
matchPlayer as mp
INNER JOIN (
SELECT playerID, matchID, SUM(runs) AS runs_by_match
FROM matchPlayer
GROUP BY playerID, matchID
) AS ms ON mp.playerID = ms.playerID
GROUP BY
ms.playerID, mp.name