I’ve made a query to count and rank every row for a table, but I can’t join the query into one table.
I’ve been trying to make a leaderboard and I’ve managed to make a query that ranks every row based on the amount of points they have (ie. 1st, 2nd, 3rd, etc). Due to my SQL version, I’ve had to use a workaround to ROW_NUMBER() and I’m struggling to include that query in this INNER JOIN query I’ve already got.
INNER JOIN query:
$query = mysqli_query($conn, "SELECT students.username,
CONCAT(spoints.points, 'pts') AS pointspts,
CONCAT(students.firstname, ' ', students.lastname) AS name,
CASE WHEN sex = 'M' THEN 'Male' ELSE 'Female' END AS sexes,
students.house,
CONCAT(students.age, 'yrs') AS ageyrs
FROM students
INNER JOIN spoints ON students.username=spoints.username
ORDER BY points DESC");
The COUNT(*)
query in which I’m trying to merge into the INNER JOIN
query:
$rank = mysqli_query($conn, "SELECT username, 1 + ( SELECT count(*) FROM spoints a WHERE a.points > b.points ) AS rank
FROM spoints b
ORDER BY rank;");
I’m trying to link these up so they’ll form one succinct table, which is where the issue is arising.
I’ve tried a large variation of code joining them, such as:
$query = mysqli_query($conn, "SELECT students.username,
CONCAT(spoints.points, 'pts') AS pointspts,
CONCAT(students.firstname, ' ', students.lastname) AS name,
CASE WHEN sex = 'M' THEN 'Male' ELSE 'Female' END AS sexes,
students.house, CONCAT(students.age, 'yrs') AS ageyrs,
(SELECT 1 + (SELECT count(*) FROM spoints a WHERE a.points > b.points ) AS rank FROM spoints b) AS rank
FROM students
INNER JOIN spoints ON students.username=spoints.username
ORDER BY points DESC");
But that only seems to return a blank column or a "mysqli_query(): (21000/1242): Subquery returns more than 1 row"
error.
I’ve also tried merging the queries with two mysqli_fetch_arrays
but then I have this mutually exclusive problem in which only the first column of either the $rank query
, or the $query query
will print. I.e.
while ($roow = mysqli_fetch_array($rank)){
while ($row = mysqli_fetch_array($query)){
printf("
<tr>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
</tr>", $roow['rank'], $row['name'], $row['ageyrs'], $row['sexes'], $row['house'], $row['pointspts']
);
}
}
returns:
Standing | Name | Age | Sex | House | Points |
---|---|---|---|---|---|
1st | Kogan Spaghetti | 17yrs | Male | Tasman | 234pts |
1st | Ami Beckler | 12yrs | Female | Pacific | 24pts |
1st | Jan Schuette | 18yrs | Male | Coral | 0pts |
OR
while ($row = mysqli_fetch_array($query)){
while ($roow = mysqli_fetch_array($rank)){
printf("
<tr>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
<td>%s</td>
</tr>", $roow['rank'], $row['name'], $row['ageyrs'], $row['sexes'], $row['house'], $row['pointspts']
);
}
}
returns:
Standing | Name | Age | Sex | House | Points |
---|---|---|---|---|---|
1st | Kogan Spaghetti | 17yrs | Male | Tasman | 234pts |
2nd | Kogan Spaghetti | 17yrs | Male | Tasman | 234pts |
3rd | Kogan Spaghetti | 17yrs | Male | Tasman | 234pts |
I want my code to return this:
Standing | Name | Age | Sex | House | Points |
---|---|---|---|---|---|
1st | Kogan Spaghetti | 17yrs | Male | Tasman | 234pts |
2nd | Ami Beckler | 12yrs | Female | Pacific | 24pts |
3rd | Jan Schuette | 18yrs | Male | Coral | 0pts |
with the code I’ve already created which is clearly capable of doing so.
How do I merge these queries so they may all print together?
2
Answers
here’s an example of how I believe it’s a better way to get the expected data, I hope it helps.
Edited in more detail for better understanding.
Result
sample database
php exemple
diagram
If you made this a two stage process where the first stage is to generate a
view
of the data that accounts for the addition of scores then the second stage could use thatview
to then perform the rank calculation.Borrowing slightly the table schema ( lightly modified ) from @Rafa Akito’s answer – viz:
Then creating the
view
:And finally the ranking calculation query:
The above query then yields:
If you combine that with your own function ( found here ) – viz:
You could then modify the above query to become:
Which itself yields:
The
view
is simple to modify to include theyrs
orMale
/Female
of course and it should be noted that later versions ofmySQL
– 8+ – have therank()
function built-in but the above was done within mySQL 5.5.8A modified
view
:That then yields the result more akin to the desired result:
Which, when plugged into PHP, could yield final HTML as follows: