Das ist nicht wirklich wahr. Es wird eine zufällige Zeile zurückgegeben. In der Praxis ist dies oft die erste Zeile in der Reihenfolge der Primärschlüssel, aber es gibt keine Garantie. Andere Datenbanken als MySQL erlauben diese Praxis nicht und lösen einen Fehler aus.
Jedenfalls besteht eine Möglichkeit, die höchste ID ungelesener Nachrichten abzurufen, darin, der Nachrichtentabelle zweimal beizutreten. Der zweite Join sucht nur nach ungelesenen Nachrichten. Zum Beispiel:
SELECT max(msg.ID) as MaxID
, messages.from
, max(unread.ID) as MaxUnreadID
, users.userName
FROM users
join messages msg
on users.ID = msg.from
and messages.to = ?
left join
messages unread
on users.ID = unread.from
and messages.to = ?
and unread.read = 0
GROUP BY
users.ID
, users.userName