ВведениеКак объединить эти два запроса для вычисления изменения ранга?
У меня есть таблица рекордов для моей игры, в которой используются ранги. Таблица баллов представляет текущие рекорды и информацию о игроке, а недавняя таблица представляет все недавно опубликованные оценки пользователем, который может быть или не быть новым верхним счетом.
Снижение уровня рассчитывается путем вычисления текущего ранга игрока за вычетом того, с какого числа они были в пути до достижения последней оценки.
Увеличение ранга рассчитывается путем расчета ранга игрока, который он имел во время достижения своего последнего максимального результата, за вычетом ранга, который у них был на момент достижения своего предыдущего верхнего балла.
Наконец, как написано в коде: $change = ($drop > 0 ? -$drop : $increase);
Вопрос
Я использую следующие два запроса в сочетании с небольшим количеством PHP кода для вычисления изменения ранга. Он работает отлично, но иногда немного медленнее.
Был ли способ оптимизировать или объединить два запроса + PHP-код?
Я создал SQL скрипку первого запроса: http://sqlfiddle.com/#!9/30848/1
Таблицы заполняются содержанием уже, так что их структуры не должны быть изменены.
Это текущий рабочий код:
$q = "
select
(
select
coalesce(
(
select count(distinct b.username)
from recent b
where
b.istopscore = 1 AND
(
(
b.score > a.score AND
b.time <= a.time
) OR
(
b.score = a.score AND
b.username != a.username AND
b.time < a.time
)
)
), 0) + 1 Rank
from scores a
where a.nickname = ?) as Rank,
t.time,
t.username,
t.score
from
scores t
WHERE t.nickname = ?
";
$r_time = 0;
if($stmt = $mysqli->prepare($q))
{
$stmt->bind_param('ss', $nick, $nick);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($r_rank, $r_time, $r_username, $r_score);
$stmt->fetch();
if(intval($r_rank) > 99999)
$r_rank = 99999;
$stmt->close();
}
// Previous Rank
$r_prevrank = -1;
if($r_rank > -1)
{
$q = "
select
coalesce(
(
select count(distinct b.username)
from recent b
where
b.istopscore = 1 AND
(
(
b.score > a.score AND
b.time <= a.time
) OR
(
b.score = a.score AND
b.username != a.username AND
b.time < a.time
)
)
), 0) + 1 Rank
from recent a
where a.username = ? and a.time < ? and a.score < ?
order by score desc limit 1";
if($stmt = $mysqli->prepare($q))
{
$time_minus_one = ($r_time - 1);
$stmt->bind_param('sii', $r_username, $time_minus_one, $r_score);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($r_prevrank);
$stmt->fetch();
if(intval($r_prevrank) > 99999)
$r_prevrank = 99999;
$stmt->close();
}
$drop = ($current_rank - $r_rank);
$drop = ($drop > 0 ? $drop : 0);
$increase = $r_prevrank - $r_rank;
$increase = ($increase > 0 ? $increase : 0);
//$change = $increase - $drop;
$change = ($drop > 0 ? -$drop : $increase);
}
return $change;
Возможно, переход на PDO делает его немного быстрее, но, вероятно, он ничего не сделает. – Tom
Не могли бы вы объяснить: – gfunk
Не могли бы вы определить 1. что представляют собой две таблицы и 2. что ваш алгоритм/математика для вычисления ранга? Из того, что я понял, мой рейтинг - это число новых записей других народов, которые набрали больше * и *, произошедших раньше (по времени), чем моя запись в таблице «баллов». плюс игнорирование! istopscoes – gfunk