В общем, самый жизнеспособный способ оказался через таблицу с позициями , транзакции и крон.
include 'bdconnect.php';
mysqli_begin_transaction($link, MYSQLI_TRANS_START_READ_WRITE);
mysqli_query($link,"TRUNCATE TABLE top_pos;");
mysqli_query($link,"SET @position_number := 0;");
mysqli_query($link,"SET @rating_id := '';");
mysqli_query($link,"INSERT INTO
top_pos (element_id, `position`, rating_id)
SELECT
id_elem,
IF(@rating_id = e.id_top, @position_number := @position_number + 1, @position_number := 1) AS position_number,
@rating_id := id_top AS rating_id
FROM
top_elements AS e
ORDER BY
e.id_top,
e.rating DESC,
e.id_elem;");
mysqli_query($link,"SET @position_number := 0;");
mysqli_query($link,"SET @rating_id := '';");
mysqli_query($link,"UPDATE
top_elements AS e
INNER JOIN
(SELECT
e.id_elem,
IF(@rating_id = e.id_top, @position_number := @position_number + 1, @position_number := 1) AS position_number,
@rating_id := id_top AS rating_id
FROM
top_elements AS e
ORDER BY
e.id_top,
e.rating DESC,
e.id_elem) AS t ON t.id_elem = e.id_elem
SET
e.position = t.position_number;");
mysqli_commit($link);
mysqli_close($link);