Помогайте парни. Мой мозг в пятницу просит пощады. Может быть пока формулирую задачу, решение вызреет. Короче, полагаюсь на эффект резинового утёнка. Есть: В каждый момент пользователю назначен какой-то уровень из таблицы levels(id, level_name, rank) и пользователь имеет ссылку вида users.level_id Уровни упорядочены по rank, чем он больше, тем "выше" уровень. Но, как обычно, не гарантированно, что rank прописан явно. Он по дефолту 0. Когда rank равен у двух записей, то порядок просто по id. Т.е. вывод по порядку роста уровня будет такой: Код (SQL): SELECT * FROM levels ORDER BY rank ASC, id ASC https://www.db-fiddle.com/f/wUDBMnQ9WeHu1CY6YuqmGd/0 Требуется: Выбрать "предыдущий" или "следующий" уровень чтобы изменить ранг пользователя. Без грёбаных циклов, в один SQL запрос. Если уровень крайний, то допустимо получить "пусто" в результате, это не проблема. Если БЫ rank был гарантированно назначен и уникален, то формула была бы такой — уровень выше, чем уже назначенный пользователю уровень: Код (SQL): SELECT l.* FROM levels AS l, (SELECT * FROM levels WHERE id = :user_level_id) AS ul WHERE l.rank > ul.rank ORDER BY l.rank ASC LIMIT 1 Но если мы усложняем задачу дефолтовыми и неуникальными rank, то по-моему так: Код (SQL): SELECT l.* FROM levels AS l, (SELECT * FROM levels WHERE id = :user_level_id) AS ul WHERE l.rank > ul.rank OR (l.rank = ul.rank AND l.id > ul.id) ORDER BY l.rank ASC, l.id ASC LIMIT 1 Я прав или нет?
А так не проще?: Код (Text): SELECT id,level_name FROM levels WHERE (rank > :user_old_rank ) OR (rank=:user_old_rank AND (id >:user_old_rank_id)) ORDER BY levels.rank ASC, levels.id ASC limit 1
@Дюран спасибо, это мой запрос, фактически. понимаешь, чтобы твоя версия заработала. надо сначала получить отдельным запросом тот самый SELECT * FROM levels WHERE id = :user_level_id , на который ты упростил мою версию ))) в общем, эффект утёнка достигнут. пока писал, сам себе доказал верность выбранного пути.