Most recent distinct record from a joined MySQL table - mysql

I have two tables, one of a list of competition results, and one with ELO ratings (based on previous competitions).
Fetching the list of competitors for an arbitrary competition is trivial enough, but I also need to get the most recent rating value for them.
score:
id | eventid | competitorid | position
1 1 1 1
2 1 2 2
3 1 3 3
4 2 2 1
5 2 3 2
6 3 1 1
7 3 3 2
8 3 2 3
rating:
id | competitorid | rating
1 1 1600
2 2 1500
3 3 1500
4 2 1600
5 3 1590
Expected output for a query against score.eventid = 3 would be
id | competitorid | position | rating
6 1 1 1600
7 3 2 1590
8 2 3 1600
At the moment my code looks like:
SELECT score.scoreID, score.competitorID, score.position,
rating.id, rating.rating
FROM score, rating
WHERE score.competitorid = rating.competitorid
AND score.eventid = 3
ORDER BY score.position
which gives an output of
id | competitorid | position | rating.id | rating
6 1 1 1 1600
7 3 2 2 1500
7 3 2 4 1590
8 2 3 3 1500
8 2 3 5 1600
basically it's showing the data from the score table for that correct event, but giving me a row for every rating available against that competitorID unfortunately I have no idea where to build in the DISTINCT statement or how to limit it to the most recent result.
MySQL noob, and managed DISTINCT statements, but not with joins. Unfortunately most previous questions seemed to deal with getting distinct results from a single table, which is not quite what I'm after. Thanks!

One way to get the rating is with a correlated subquery:
SELECT s.scoreID, s.eventID, s.competitorID, s.position,
(select r.rating
from rating r
where s.competitorID = r.competitorID
order by r.id desc
limit 1
) as rating
FROM score s
WHERE s.eventID = 3
ORDER BY s.position;
I'm not sure what ratingprid is, so this only includes the rating.

Related

MySQL group rows

I have a table with:
Id (id of rider)
Time (is the time that he has done)
Session (number session where the time was done)
idlap idRider session time
1 45652 1 4
2 54645 1 2
3 45652 2 2
4 54582 2 1
5 51284 1 3
6 54582 1 3
7 54645 2 4
8 51284 2 5
9 54582 2 2
I wonder how to query in MySQL a result like:
idRider |fast sesion | count laps
45652 | 2 | 1
54645 | 1 | 1
51284 | 3 | 1
54582 | 2 | 2
The query should return in which session the rider got the best time(fast session) and count the number of laps (done in the fast session) grouped by idRider.
Thank you.
This query will give you the results that you want. It JOINs the laps table to the minimum time and number of laps per rider per session, and then to the minimum time per rider to get the fastest session:
SELECT l.idRider, l.session, l.time, s.numlaps
FROM laps l
JOIN (SELECT idRider, `session`, MIN(time) AS fastest, COUNT(*) AS numlaps
FROM laps
GROUP BY idRider, `session`) s ON s.idRider = l.idRider AND s.session = l.session AND s.fastest = l.time
JOIN (SELECT idRider, MIN(time) AS fastest
FROM laps
GROUP BY idRider) f ON f.idRider = s.idRider AND f.fastest = s.fastest
ORDER BY idRider
Output:
idRider session time numlaps
45652 2 2 1
51284 1 3 1
54582 2 1 2
54645 1 2 1
Demo on dbfiddle

MySQL Relative ranking of values in one column for all occurrences of a given key

I'm looking for some basic direction on how where to start looking to try and rank rows of a common key in a query.
Imagine I have a table like this:
user_id | account_id | score
1 A 10
1 B 20
2 C 10
2 D 20
2 E 30
What I'm hoping to do is add a rank column for relative to each user_id where the highest score gets the top rank:
user_id | account_id | score | rank
1 A 10 2
1 B 20 1
2 C 10 3
2 D 20 2
2 E 30 1
Just looking for some basic direction in terms of which way to head :/
You can use subquery
select
*,
(select count(1)+1 from your_table b where a.user_id=b.user_id and a.score<b.score) as rank
from your_table a
Output
1 A 10 2
1 B 20 1
2 C 10 3
2 D 20 2
2 E 30 1

How to check for one value in multiple rows

Whats the best way to check if different groups of rows in a table with the same GroupID such as different teams have a SINGLE captain? Captain Identifier for example could be '10', so its crucial that it goes through multiple records with the same groupID and checks to see if theres ONLY ONE record with the positionID as '10'. I need it to do it for all teams, i.e all groupID's
-------------------------------------------------
ID | Group ID | Name | Position|
-------------------------------------------------
1 1 John 3
2 1 jim 3
3 1 Hahn 4
4 1 Mary 4
5 1 Moe 4
6 1 Charlie 10
7 2 taylor 4
8 2 Geoff 4
9 2 adam 4
10 2 cam 10
11 3 sharon 2
12 3 tony 4
13 3 steve 3
14 3 eve 4
15 3 gwen 10
--------------------------------
So what I need it to do is check that every groupID only had ONE 10 as the position.
Thanks in advance guys. Check out the image link at the bottom.
im using mysql btw
Sorry if this is badly described
If I understood you - I think you need something like :
select groupId, sum(case when positionID='10' then 1 else 0 end) as captains
from tbl_name
group by groupID
having captains = 1
am I close???
If I understood you correctly, you want an indication that will tell you whether the groupID had more then one captain.
So what you need is this:
select groupID,case when cnt = 1 then 1 else 0 end as IND_ONE_CAPTAIN from (
select groupID, sum(case when positionid = '10' then 1 else 0 end) as cnt
from players
group by groupID)
Now IND_ONE_CAPTAIN columns consist 1 or 0, 1 is for the group id only had 1 captain, and 0 is when they had more.

Select min/max from multiple items

I'll try to explain it as simple as possible:
First some database structure with dummy data.
Structure
tb_spec_fk
feature value
-----------------
1 1
1 2
1 3
1 4
1 5
2 2
2 3
3 1
3 4
4 2
4 3
4 4
5 1
5 3
5 5
6 3
6 5
tb_spec_feature
feature_id filter
------------------
1 2
2 2
3 2
4 2
5 1
6 0
tb_spec_value
value_id name
----------------
1 10
2 20
3 30
4 40
5 50
Now, what I want is the follow result
Result
feature_id min_value max_value
---------------------------------
1 10 50
2 20 30
3 10 40
4 20 40
But how?
Logic
Get from the tb_spec_feature where "filter" equals 2 the highest and lowest values which are present in the tb_spec_value table and connected together trough the tb_spec_fk table.
My attemps
A lot! But I'll spare you :)
SELECT
f.feature_id AS feature_id,
MAX(value.name) AS max_value,
MIN(value.name) AS min_value
FROM tb_spec_feature AS f
JOIN tb_spec_fk AS fk ON f.feature_id=fk.feature
JOIN tb_spec_value AS value ON fk.value=value.id
WHERE f.filter=2
GROUP BY f.feature_id
The two JOIN statements "link" the a feature to a value. GROUP BY groups all rows with the same feature id, and then you can take the min or max or any other aggregate function on those columns.
Demo
Here is how you can do it
select
tsf.feature_id,
tsvl.name as Min_Value,
tsvr.name as Max_Value
from tb_spec_feature as tsf
inner join (select feature , MIN(value) MinV,MAX(value)MaxV from tb_spec_fk group by feature order by feature)as tsfkl on tsfkl.feature = tsf.feature_id
left join tb_spec_value as tsvl on tsvl.value_id = tsfkl.MinV
left join tb_spec_value as tsvr on tsvr.value_id = tsfkl.MaxV
where tsf.filter = 2
group by tsf.feature_id
Output
feature_id | Min_Value | Max_Value
---------------------------------
1 | 10 | 50
2 | 20 | 30
3 | 10 | 40
4 | 20 | 40
Fiddle Demo

complex sql query in sql server 2008

I have 4 major tables in my database.
Season --> seasonID
Trials --> trialID
Competition --> CID,name
Camps --> campID,DivisionID(FK)
Divisions ---> DivisionID
Contestants --->ContestantID
Now a contestant belongs to / are members of a divisions.
Then a division belongs to a camp.
All this leads to my Performance table.
PERFORMANCE TABLE
SeasonID|TrialID|CampID|DivID|CompetionID|CtestantID|Score1 |Score2 |Total
1 1 1 1 1 1 20 20 40
1 1 1 1 2 1 20 15 30
1 2 1 1 1 2 10 5 15
1 2 1 1 2 2 5 5 10
1 2 1 1 1 1 10 30 40
1 2 1 1 2 1 20 10 30
How can I query this performance table to give me the competition name, total score and rank (ranking over total score) of each contestant in each competition by trials and by seasons?
Example:
In season 1 and trial 2 I want to have:
SeasonID| TrialID | ContestantID| Competition | TotalScore | Rank
1 2 1 1 40 1
1 2 2 1 15 2
1 2 1 2 30 1
1 2 2 2 10 2
How do I go about this? I have tried table variables, pivot and joins but I can only rank by competitions, but I don't how to aggregate the results to get the result above!
I'm not exactly sure how you calculated your desired results. I think this is what you are after but, if so, the TotalScore in the desired results of your question should be 10 for the last record, not 20.
SELECT SeasonID, TrialID, ContestantID, CompetitionID, Total,
DENSE_RANK() OVER(PARTITION BY CompetitionId ORDER BY Total DESC) AS [Rank]
FROM PerformanceTable