Spaces are free!
It's a good idea to space out your code for readability. @Vogel612 did this in his answer (perhaps subconsciously), but it doesn't hurt to say it explicitly.
SELECT
multiple columns without *
.
You mentioned using SELECT *
. This is typically considered poor design; it's preferable to explicitly list the columns you want SELECT
ed, so you can do SELECT user, score
. (This is because if you add many more columns but you don't use them, you're making the database engine do more work. It also makes it easy to see what columns exist and are used, whereas SELECT *
will force you to look it up.)
Design your database carefully.
There is rarely a good reason to not include an id
primary key column in a table. It allows for future cross-referencing as well as performance improvements. Since you want the latest users, then you should also include a TIMESTAMP
-typed column defaulting to CURRENT_TIMESTAMP
. Then you'll be able to rewrite your query as SELECT `user`, `score` FROM `ris_universita` ORDER BY `timestamp` DESC LIMIT 10
. Note that you don't need to SELECT
the id
column here.
Be consistent with string delimiters.
You use single quotes and double quotes interchangeably. Since you are neither using string interpolation, nor avoiding escape codes, nor printing out single- or double quotes, you have no reason to use one over the other. Just pick one that you like and use it throughout.
The other answers provided excellent points that I tried not to repeat. (The point on comments is especially important.) Here I propose an alternative solution to using a buffer: mysqli_data_seek
. This would save on a little bit of memory compared to the buffer solution, which could be significant if you were selecting millions of rows rather than ten. However, this is probably still not as good as just using a table, as @Rick suggested.
<?php
$connection = mysqli_connect();
$result = mysqli_query($connection, 'SELECT `user`, `score` FROM `ris_universita` ORDER BY `timestamp` DESC LIMIT 10');
echo 'Latest users who tried our test:<br>';
while ($row = mysqli_fetch_assoc($result)) {
echo $row['user'], '<br>';
}
mysqli_data_seek($result, 0);
echo 'Users got the following scores:<br>';
while ($row = mysqli_fetch_assoc($result)) {
echo $row['score'], "<br>";
}
?>
Or with error checking, string interpolation, and cleanup, written OO-style:
<?php
$mysqli = new mysqli();
if ($mysqli->connect_errno) {
echo "Failed to connect to MySQL: $mysqli->connect_error\n";
return; // in case this file is included, return is probably better than die
}
$query = "SELECT `user`, `score` FROM `ris_universita` ORDER BY `timestamp` DESC LIMIT 10";
if ($result = $mysqli->query($query)) {
echo "Latest users who tried our test:<br />\n";
while ($row = $result->fetch_assoc()) {
echo "$row[user]<br />\n";
}
$result->data_seek(0);
echo "Users got the following scores:<br />\n";
while ($row = $result->fetch_assoc()) {
echo "$row[user]<br />\n";
}
$result->close();
} else {
echo "Query failed: $query";
}
$mysqli->close();
?>
LIMIT
withoutORDER BY
rarely makes good sense? \$\endgroup\$ORDER BY
, the optimizer will return rows in whatever order it feels like. If either one of those columns starts an index, it's probably going to start with that. A pair of queries is unlikely to match users and scores. Don't rely on auto-generated ids for insertion order, especially for concurrent systems and anything with triggers: they can only be relied upon to give you a unique value. Use aninsertedAt
timestamp column for that information (which also makes updating erroneous rows easier). \$\endgroup\$