Currently I am developing a system to support a competition. In this competition there are 11 judges that give a grade to the participant. This grade is stored in a table per judge. With the following Select statement I retrieve the total score from the MySQL database (and also some inner joins to select other information from other tables).
Now I want to have ranking in this system, where also ex aequo is taken into account. I have tried several mysql solutions from this forum. But somehow the statement is always incorrect. Hopefully, someone can help me.
SELECT optreden.id, optreden.wedstrijd, optreden.jaartal,
liedje.titel, club.volledige_clubnaam,
(SELECT SUM(score.score_lied) FROM score WHERE score.optreden=optreden.id) AS score
FROM optreden
INNER JOIN liedje ON optreden.liedje=liedje.id
INNER JOIN club ON liedje.uitvoerende_club=club.id
WHERE optreden.wedstrijd="voorselectie" AND optreden.jaartal=2014
GROUP BY optreden.id
ORDER BY score_lied DESC
With this query, I get the following result:
+----+--------------+------+----------+--------------+------+
| id | Competition | Year | Title | Artist (club)| Score|
+----+--------------+------+----------+--------------+------+
| 12 | voorselectie | 2014 | Song 1 | Club 1 | 792 |
| 16 | voorselectie | 2014 | Song 2 | Club 2 | 600 |
| 10 | voorselectie | 2014 | Song 3 | Club 3 | 600 |
| 11 | voorselectie | 2014 | Song 3 | Club 3 | 500 |
| 12 | voorselectie | 2014 | Song 3 | Club 3 | 400 |
The query fetches information from the following tables:
Score: in this table the scores given by the 11 judges is stored as
line-items (result is given below);
Optreden: in this table the information from the club and the song is linked;
Club: information from the club,
such as name;
Liedje: information about the song, performed by the
club.
All the tables are linked by id's. In the result, there should come a column, with the ranking of the club.
The result from the table score is as follows:
+----+----+--------+----+
| ID | Pid| Userid | 85 |
+----+----+--------+----+
| 1 | 12 | 444 | 85 |
| 12 | 12 | 454 | 92 |
| 13 | 12 | 445 | 87 |
| 14 | 12 | 446 | 56 |
| 15 | 12 | 447 | 81 |
| 16 | 12 | 448 | 78 |
| 17 | 12 | 449 | 55 |
| 18 | 12 | 450 | 69 |
| 19 | 12 | 451 | 88 |
| 20 | 12 | 452 | 69 |
| 21 | 12 | 453 | 32 |
+----+----+--------+----+
Where the columns represent the following:
- ID: the id of the score in the table;
- Pid: the id of the performance (with this performing club and song are linked);
- Userid: the userid of the 11 judges;
- Score: the score given by each judge.
The end result should be as follows:
+----+--------------+------+----------+--------------+------+------+
| id | Competition | Year | Title | Artist (club)| Score| Rank |
+----+--------------+------+----------+--------------+------+------+
| 12 | voorselectie | 2014 | Song 1 | Club 1 | 792 | 1 |
| 16 | voorselectie | 2014 | Song 2 | Club 2 | 600 | 2 |
| 10 | voorselectie | 2014 | Song 3 | Club 3 | 600 | 2 |
| 11 | voorselectie | 2014 | Song 3 | Club 3 | 500 | 4 |
| 12 | voorselectie | 2014 | Song 3 | Club 3 | 400 | 5 |
I have tried the solution from Neville before and now again. I have rewritten the SQL statement as follows:
SELECT optreden.id, optreden.wedstrijd, optreden.jaartal,
liedje.titel, club.volledige_clubnaam,
(SELECT SUM(score.score_lied) FROM score WHERE score.optreden=optreden.id) AS score, CASE
WHEN #prev_value = score THEN #rank_count
WHEN #prev_value := score THEN #rank_count := #rank_count + 1
END AS rank,
FROM optreden
INNER JOIN liedje ON optreden.liedje=liedje.id
INNER JOIN club ON liedje.uitvoerende_club=club.id
WHERE optreden.wedstrijd="voorselectie" AND optreden.jaartal=2014
GROUP BY optreden.id
ORDER BY score_lied DESC
Here I get the error: Unknown column 'score' in 'field list'..
It seems that you are getting this error simply because there is no field score... I have extracted your inner SELECT into a JOIN so the real field can be used directly. (Not tested though, sorry)
SELECT optreden.id, optreden.wedstrijd, optreden.jaartal,
liedje.titel, club.volledige_clubnaam,
SUM(score.score_lied) AS score, CASE
WHEN #prev_value = SUM(score.score_lied) THEN #rank_count
WHEN #prev_value := SUM(score.score_lied) THEN #rank_count := #rank_count + 1
END AS rank,
FROM optreden
INNER JOIN liedje ON optreden.liedje=liedje.id
INNER JOIN club ON liedje.uitvoerende_club=club.id
LEFT JOIN score ON score.optreden=optreden.id
WHERE optreden.wedstrijd="voorselectie" AND optreden.jaartal=2014
GROUP BY optreden.id
ORDER BY score_lied DESC
Please note that you might face another little problem with this kind of ranking: Normally, when two entities end up on the same rank, the next rank is not given to the next person. Here's what I mean with an example, with two persons ranking in 3:
1, 2, 3, 3, 5
But in your code, it will give:
1, 2, 3, 3, 4
I hope this helps.
I have tried several things. However, I had forgotten to tell you one important feature I was gonna use. The ranking of the clubs should be presented through a presentation on a big screen. Therefor the MySQL code changed a little.
I have added a support table to my database. In this support table the sum of the scores is recorded with a INSERT INTO...SELECT statement.
When this insert is done. An update script is launched which makes the ranking in the table and also makes a correct calculation for ex aequo.
Here's the update statement:
SET #rank=0, #last_score = null, #tie_build_up = 0;
UPDATE ranking_voorselectie_lied
SET rank= #rank:= if(#last_score = totaal_score_lied, #rank, #rank+#tie_build_up+1),
tie_build_up= #tie_build_up:= if(#last_score = totaal_score_lied, #tie_build_up+1, 0),
last_score= #last_score:= totaal_score_lied
WHERE wedstrijd="voorselectie" AND jaar=2014
ORDER BY totaal_score_lied DESC;
This gives me the following result:
+--------------+------+----------+-------------------+------+-----+------------+
| Wedstrijd | Jaar | Optreden | totaal_score_lied | Rank | Tie | last_score |
+--------------+------+----------+-------------------+------+-----+------------+
| voorselectie | 2014 | 12 | 792 | 1 | 0 | 792 |
| voorselectie | 2014 | 16 | 82 | 2 | 0 | 82 |
| voorselectie | 2014 | 10 | 73 | 3 | 0 | 73 |
| voorselectie | 2014 | 15 | 51 | 4 | 0 | 51 |
| voorselectie | 2014 | 3 | 50 | 5 | 0 | 50 |
| voorselectie | 2014 | 11 | 42 | 6 | 0 | 42 |
| voorselectie | 2014 | 13 | 38 | 7 | 0 | 38 |
| voorselectie | 2014 | 8 | 38 | 7 | 1 | 38 |
| voorselectie | 2014 | 14 | 37 | 9 | 0 | 37 |
| voorselectie | 2014 | 5 | 35 | 10 | 0 | 35 |
| voorselectie | 2014 | 4 | 33 | 11 | 0 | 33 |
| voorselectie | 2014 | 7 | 25 | 12 | 0 | 25 |
| voorselectie | 2014 | 9 | 23 | 13 | 0 | 23 |
+--------------+------+----------+-------------------+------+-----+------------+
Related
---------------------------------------------------------------------
id | stid | Subject | Total_cumulative | Year |
----------------------------------------------------------------------
1 | 23 | English | 40 | 2014/2015
2 | 1 | English | 29 | 2014/2015
3 | 13 | Maths | 40 | 2014/2015
4 | 4 | Physics | 60 | 2014/2015
5 | 13 | Commerce | 40 | 2014/2015
6 | 1 | Biology | 89 | 2014/2015
7 | 13 | English | 29 | 2014/2015
8 | 13 | Agric | 60 | 2014/2015
Now I have a query that gets all of a particular students results as follow
SELECT * FROM results where stid='13' AND year='2014/2015'
ORDER BY subject ASC LIMIT 20
and I have the following result
---------------------------------------------------------------------
id | stid | Subject | Total_cumulative | Year |
----------------------------------------------------------------------
3 | 13 | Maths | 40 | 2014/2015
5 | 13 | Commerce | 40 | 2014/2015
7 | 13 | English | 89 | 2014/2015
8 | 13 | Agric | 60 | 2014/2015
But my aim is to get the particular students rank in each subject and I have a sub query inside my the while loop of my first sql statement as follow
SELECT rank_number, id, name, total_cumulative
FROM ( SELECT id, name, total_cumulative, #rank:=#rank+1 AS rank_number FROM
(SELECT pl.id, pl.name,SUM(en.total_cumulative) AS total_cumulative
FROM students pl JOIN results en ON pl.id = en.stid
WHERE en.subject = '$subject' AND en.year='$year'
GROUP BY pl.id ORDER BY total_cumulative DESC ) AS rankings,
(SELECT #rank:=0) AS r ) AS overall_rankings
WHERE id = '13'
LIMIT 0, 1";
after that I have the following result
----------------------------------------------------------------------------
id | stid | Subject | Total_cumulative | Year | Rank
----------------------------------------------------------------------------
3 | 13 | Maths | 40 | 2014/2015 | 1
5 | 13 | Commerce | 40 | 2014/2015 | 2
7 | 13 | English | 29 | 2014/2015 | 3
8 | 13 | Agric | 60 | 2014/2015 | 1
but I want the query to check for ties and give the results in the following order
----------------------------------------------------------------------------
id | stid | Subject | Total_cumulative | Year | Rank
----------------------------------------------------------------------------
3 | 13 | Maths | 40 | 2014/2015 | 1
5 | 13 | Commerce | 40 | 2014/2015 | 2
7 | 13 | English | 29 | 2014/2015 | 2
8 | 13 | Agric | 60 | 2014/2015 | 1
Please help me I am a newbies in mysql programming
I am actually having loads of trouble trying to obtain the rank or position of a specific row on Symfony.
Example: player table
id - name - total
1 xxxx 100
2 yyyy 200
3 www 500
When I do the following thing on the terminal, it works fine:
SELECT id, total, name, #curRank := #curRank + 1 AS rank FROM player p, (SELECT #curRank := 0) q ORDER BY total DESC
+----+-------+----------------+------+
| id | total | name | rank |
+----+-------+----------------+------+
| 19 | 1931 | guitouman | 1 |
| 2 | 1765 | lu | 2 |
| 1 | 1583 | Seyaa | 3 |
| 17 | 1532 | coucou lapinou | 4 |
| 11 | 1494 | the moine eau | 5 |
| 7 | 1446 | alien | 6 |
| 3 | 1415 | Saiyya | 7 |
| 50 | 1231 | dfdf | 8 |
| 20 | 1230 | Jrm | 9 |
| 16 | 1221 | Ragnar | 10 |
| 6 | 1182 | arachati | 11 |
| 8 | 1025 | momo | 12 |
| 10 | 789 | kingrom | 13 |
| 13 | 777 | le seur | 14 |
| 53 | 743 | aaa | 15 |
| 14 | 568 | Rakhamo | 16 |
| 9 | 466 | sapeur coco | 17 |
| 12 | 446 | chamboul | 18 |
| 51 | 321 | sdfdsf | 19 |
| 54 | 132 | | 20 |
| 52 | 46 | sdfsdf | 21 |
| 48 | 0 | dragma | 22 |
+----+-------+----------------+------+
The probleme is to get this working in Symfony2 where the "#" or "Set" keyword is not recognized. I have tried this :
$query -> $this->_em->createQuery('SET #rownum := 0;SELECT id, total, rank FROM SELECT #rownum := #rownum + 1 AS rank, id, totalTroopRecieved FROM clan ORDER BY total;')->setParameter('id', $this->getId());
return $query->getResult();
Which gives this error:
[Syntax Error] line 0, col 24: Error: Expected IdentificationVariable | ScalarExpression | AggregateExpression | FunctionDeclaration | PartialObjectExpression | "(" Subselect ")" | CaseExpression, got '#'
I feel desperate .. Spending 2 days for this when i know it works via sql queries but not on symfony makes me mad ..
I tried NUMBER_ROW() or RANK() function but it does not seem to work on Mysql.
Thank you for your precious help.
I'm making a rank based game using unity. But I got stuck in the query for the best match please help me out.
The SQL Query:
SELECT name, high_score, #rn:=#rn+1 as row_num
FROM score, (select #rn:=0) as r
ORDER BY high_score DESC
The SQL Table:
row_number | score | firstname
-------------------------------
1 | 210 | Bill
2 | 431 | Linus
3 | 352 | Rasmus
4 | 173 | Steve
5 | 294 | Ross
6 | 411 | Henry
7 | 313 | Jagannath
8 | 115 | Samit
9 | 217 | Vishal
10 | 419 | Tanuj
11 | 321 | Harshad
12 | 123 | Parag
13 | 225 | Aman
14 | 427 | Amar
15 | 329 | Madhur
16 | 131 | Sachin
I want the result like below:
For name'Ross' i.e on 7th position between high and low scores.
Note: The database has thousands of users but result must be 15.
http://i.stack.imgur.com/CroRd.png
Consider the following. Note, I've used 11 instead of 15 in this example (just because it was easier to test against the sample data set). Also, my core algorithm is slower than yours and it doesn't account for ties - so you may want to switch it for something like yours, which is faster, and does!
DROP TABLE IF EXISTS score;
CREATE TABLE score
(score INT NOT NULL,firstname VARCHAR(20) NOT NULL PRIMARY KEY);
INSERT INTO score VALUES
(210 ,'Bill'),
(431 ,'Linus'),
(352 ,'Rasmus'),
(173 ,'Steve'),
(294 ,'Ross'),
(411 ,'Henry'),
(313 ,'Jagannath'),
(115 ,'Samit'),
(217 ,'Vishal'),
(419 ,'Tanuj'),
(321 ,'Harshad'),
(123 ,'Parag'),
(225 ,'Aman'),
(427 ,'Amar'),
(329 ,'Madhur'),
(131 ,'Sachin');
SELECT score,firstname,rank
FROM
( SELECT b.*
FROM
( SELECT x.*
, COUNT(*) rank
FROM score x
JOIN score y
ON y.score >= x.score
GROUP
BY firstname,score
) a
JOIN
( SELECT x.*
, COUNT(*) rank
FROM score x
JOIN score y
ON y.score >= x.score
GROUP
BY firstname,score
) b
WHERE a.firstname = 'Ross'
AND ABS(b.rank-a.rank) <=15
ORDER
BY ABS(b.rank-a.rank) LIMIT 11
) n
ORDER
BY rank;
+-------+-----------+------+
| score | firstname | rank |
+-------+-----------+------+
| 411 | Henry | 4 |
| 352 | Rasmus | 5 |
| 329 | Madhur | 6 |
| 321 | Harshad | 7 |
| 313 | Jagannath | 8 |
| 294 | Ross | 9 |
| 225 | Aman | 10 |
| 217 | Vishal | 11 |
| 210 | Bill | 12 |
| 173 | Steve | 13 |
| 131 | Sachin | 14 |
+-------+-----------+------+
This is a simplification table structure that i have.
I have two tables.
TABLE 1
ID PTS PID TID
----------------------------------------
1 3 1 22
2 10 1 22
3 5 1 22
4 1 2 58
5 0 2 58
7 0 3 47
8 5 3 47
15 5 4 51
15 3 4 51
9 7 3 6
10 0 1 8
11 2 1 8
12 4 5 1
13 1 6 9
14 2 5 12
15 5 4 61
15 6 4 61
15 2 4 61
16 0 7 100
ect. ect. ect. ect.
TABLE 2
NAME PID
-------------------
Jhon 1
Peter 2
Lisa 3
Doe 4
Joey 5
Mike 6
Debby 7
ect. ect.
Now i need to select the latest two PTS from each TID and match them whit PID row on table 2. and calculate the Average.
THE DESIRED OUTCOME
NAME AVG
-------------------
Jhon 4,25
Peter 1,00
Lisa 6,00
Doe 4,00
Joey 3,00
Mike 1,00
Debby 0,00
ect. ect.
Clarification: the PID row are relational. Multiple TIDs can have the same PID and TIDs can have multiple PTS. I am using PDO socket.
At the time my query is:
$query = $db->prepare("SELECT IFNULL(AVG(pts), 0) AS P, TA1.PID AS TA1PID, name AS N FROM ".
"table1 TA1 LEFT JOIN table2 TA2 ON TA1.PID = TA2.PID ".
"GROUP BY name, TA2.PID ".
"ORDER BY TA1.id DESC");
But this calculates all the points(PTS) from TID. but i would like to only calculate the Two latest points(PTS) per TID. I have tried different queries the whole day but i cant figure it out. I am pretty new to SQL I managed to get one example working but with pure PHP and its not pretty :D
sqlFiddle: LINK
The problem is that it calculates all the TID points in Average. It only should calculate the two last entries per TID
I hope this is a clear question. I have tried my best to explain my problem. If any questions please ask. I have read other similar problems than mine here on Stackoverflow but i could not modify them to work for me.
You can select only the most recent 2 rows from the first table using this query
select t1.id, t1.pts, t1.pid, t1.tid
from table1 t1
join table1 t2 on t2.id >= t1.id and t1.tid = t2.tid
group by t1.id
having count(*) <= 2
and plug it into your original query instead of table 1
SELECT IFNULL(AVG(pts), 0) AS AVG, TA1.PID AS
Table1_ID, name AS Name FROM
(
select t1.id, t1.pts, t1.pid, t1.tid
from table1 t1
join table1 t2 on t2.id >= t1.id and t1.tid = t2.tid
group by t1.id
having count(*) <= 2
)
TA1 LEFT JOIN table2 TA2 ON TA1.PID = TA2.PID
GROUP BY name, TA2.PID
ORDER BY TA1.id DESC
Group Per N are pretty easy in Most DBs. Just use ROW_NUMBER. Unfortunately MySQL doesn't have them so we must simulate it
SELECT name,
Avg(PTS)
FROM
(
SELECT *,
CASE
WHEN #previousPID IS NULL
OR #previousTID IS NULL
OR ( #previousPID = ORDERED.pid
AND #previousTID = ORDERED.tid )
THEN #rownum := #rownum + 1
ELSE #rownum := 1
end rn,
#previousPID := ORDERED.pid ,
#previousTID := ORDERED.tid
FROM (SELECT t2.name,
t2.pid,
t1.id,
t1.tid ,
t1.Pts
FROM table2 t2
INNER JOIN table1 t1
ON T2.pid = t1.pid
ORDER BY t1.pid,
t1.tid,
t1.id DESC)ORDERED,
(SELECT #rownum := 0,
#previousPID := NULL,
#previousTID := NULL) t) CTE
WHERE CTE.rn <= 2
GROUP BY name
Which has the following Results
| NAME | AVG(PTS) |
|-----------|----------|
| Doe | 4 |
| Jhon | 4.25 |
| Joey | 3 |
| Lisa | 4 |
| Mike | 1 |
| No points | 0 |
| Peter | 0.5 |
DEMO
Looking at the intermediate results may help to understand how the CASE statements generate the rownumbers
| NAME | PID | ID | TID | PTS | #ROWNUM := 0 | #PREVIOUSPID := NULL | #PREVIOUSTID := NULL | RN | #PREVIOUSPID := ORDERED.PID | #PREVIOUSTID := ORDERED.TID |
|-----------|-----|----|-----|-----|--------------|----------------------|----------------------|----|-----------------------------|-----------------------------|
| Jhon | 1 | 3 | 22 | 5 | 0 | (null) | (null) | 1 | 1 | 22 |
| Jhon | 1 | 2 | 22 | 10 | 0 | (null) | (null) | 2 | 1 | 22 |
| Jhon | 1 | 1 | 22 | 3 | 0 | (null) | (null) | 3 | 1 | 22 |
| Jhon | 1 | 12 | 8 | 2 | 0 | (null) | (null) | 1 | 1 | 8 |
| Jhon | 1 | 11 | 8 | 0 | 0 | (null) | (null) | 2 | 1 | 8 |
| Peter | 2 | 5 | 58 | 0 | 0 | (null) | (null) | 1 | 2 | 58 |
| Peter | 2 | 4 | 58 | 1 | 0 | (null) | (null) | 2 | 2 | 58 |
| Lisa | 3 | 7 | 47 | 5 | 0 | (null) | (null) | 1 | 3 | 47 |
| Lisa | 3 | 6 | 47 | 0 | 0 | (null) | (null) | 2 | 3 | 47 |
| Lisa | 3 | 10 | 6 | 7 | 0 | (null) | (null) | 1 | 3 | 6 |
| Doe | 4 | 9 | 51 | 3 | 0 | (null) | (null) | 1 | 4 | 51 |
| Doe | 4 | 8 | 51 | 5 | 0 | (null) | (null) | 2 | 4 | 51 |
| Doe | 4 | 19 | 61 | 2 | 0 | (null) | (null) | 1 | 4 | 61 |
| Doe | 4 | 17 | 61 | 6 | 0 | (null) | (null) | 2 | 4 | 61 |
| Doe | 4 | 16 | 61 | 5 | 0 | (null) | (null) | 3 | 4 | 61 |
| Joey | 5 | 13 | 1 | 4 | 0 | (null) | (null) | 1 | 5 | 1 |
| Joey | 5 | 15 | 12 | 2 | 0 | (null) | (null) | 1 | 5 | 12 |
| Mike | 6 | 14 | 9 | 1 | 0 | (null) | (null) | 1 | 6 | 9 |
| No points | 7 | 18 | 100 | 0 | 0 | (null) | (null) | 1 | 7 | 100 |
I have two tables in a tournament-related database and I need to know the most optimized SQL query to generate the correct overall results. The results must show the total points scored, minus any penalties, and scores that are tied should be broken based on the person who reached that score first.
In the database tables, I have an event log where each score is added as teams proceed through the tournament, and I have another table which shows which team is part of which tournament.
Table "xTournamentTeam" (connects a team to a tournament)
=======================
+-----+------------+--------+--------------+
| nID | Team Name | TeamID | TournamentID |
+-----+------------+--------+--------------+
| 1 | Team A | 12 | 25 |
| 2 | Team B | 13 | 25 |
| 3 | Team C | 14 | 25 |
| 4 | Team D | 15 | 25 |
| 3 | Team A | 12 | 32 |
| 4 | Team B | 13 | 32 |
+-----+------------+--------+--------------+
Table "nEventLog" (records scoring during a tournament)
=================
+-----+---------------+---------+----------+----------------+-----------------------+
| nID | nTournamentID | nTeamID | nPoints | nPointsPenalty | nEventTime |
+-----+---------------+---------+----------+----------------|-----------------------+
| 1 | 25 | 15 | 100 | 0 | 1/24/2013 6:05:14 AM |
| 2 | 25 | 14 | 100 | 0 | 1/24/2013 6:29:55 AM |
| 3 | 25 | 14 | 100 | 25 | 1/24/2013 7:09:34 AM |
| 4 | 25 | 12 | 100 | 0 | 1/24/2013 7:12:28 AM |
| 5 | 25 | 12 | 100 | 0 | 1/24/2013 8:42:59 AM |
| 6 | 25 | 12 | 100 | 50 | 1/24/2013 8:43:36 AM |
| 7 | 25 | 14 | 100 | 0 | 1/24/2013 9:15:24 AM |
| 8 | 25 | 15 | 100 | 0 | 1/24/2013 9:15:27 AM |
| 9 | 32 | 12 | 100 | 0 | 1/28/2013 8:33:49 AM |
| 10 | 32 | 13 | 100 | 25 | 1/28/2013 2:15:12 PM |
| 11 | 32 | 12 | 100 | 10 | 1/28/2013 7:12:25 AM |
| 12 | 32 | 13 | 100 | 0 | 1/29/2013 7:18:06 AM |
+-----+---------------+---------+----------+----------------+-----------------------+
In the case of the above data, the query I need should generate the following results for Tournament #25:
+-------+------------+--------+--------------+---------------+---------------------+-----------------------------+
| nRank | Team Name | TeamID | TournamentID | nTotalPoints | nTotalPointsPenalty | nLatestEventTime |
+-------+------------+--------+--------------+---------------+---------------------+-----------------------------+
| 1 | Team A | 12 | 25 | 300 | 50 | 1/24/2013 8:43:36 AM |
| 2 | Team C | 14 | 25 | 300 | 25 | 1/24/2013 9:15:24 AM |
| 3 | Team D | 15 | 25 | 200 | 0 | 1/24/2013 9:15:27 AM |
| 4 | Team B | 13 | 25 | 0 | 0 | |
+-------+------------+--------+--------------+---------------+---------------------+-----------------------------+
For load purposes, I'm trying to avoid sub-queries at all costs since the final query should be as optimized as possible. The "nRank" column can be generated programatically... MySQL shouldn't have to return it, but I'm shoing it for reference.
The query I have that is the closest is this one, but it doesn't return "Team B" because they don't have any records in the "nEventLog" table for nTournamentID #25:
SELECT xTournamentTeam.nTeamName
, sum(nEventLog.nPoints) AS nTotalPoints
, xTournamentTeam.nTeamID
, max(nEventLog.nEventTime) AS nLatestEventTime
, sum(nEventLog.nPointsPenalty) AS nTotalPenaltyPoints
, xTournamentTeam.nTournamentID
FROM
xTournamentTeam
LEFT OUTER JOIN nEventLog
ON xTournamentTeam.nTeamID = nEventLog.nTeamID
WHERE
xTournamentTeam.nTournamentID = 33
AND nEventLog.nTournamentID = 33
GROUP BY
xTournamentTeam.nID
, xTournamentTeam.nTournamentID
ORDER BY
nTotalPoints DESC
, nLatestEventTime DESC
I'm certainly no expert in MySQL queries, and I've been working on this for two days without much success, so any help would be greatly appreciated.
I change your logic a little bit, I think it's working:
SELECT
xTournamentTeam.TeamName
, sum(nEventLog.nPoints) AS nTotalPoints
, xTournamentTeam.TeamID
, max(nEventLog.nEventTime) AS nLatestEventTime
, sum(nEventLog.nPointsPenalty) AS nTotalPenaltyPoints
, xTournamentTeam.TournamentID
FROM
xTournamentTeam
LEFT OUTER JOIN nEventLog
ON xTournamentTeam.TournamentID = nEventLog.nTournamentID AND xTournamentTeam.TeamID = nEventLog.nTeamID
WHERE
xTournamentTeam.TournamentID = 25
GROUP BY
xTournamentTeam.TeamID
, xTournamentTeam.TournamentID
, xTournamentTeam.TeamName
ORDER BY
nTotalPoints DESC
If you need, you can format nulls to represent 0 or something else.