За последние 24 часа нас посетили 22503 программиста и 999 роботов. Сейчас ищут 637 программистов ...

Предыдущая/следующая запись

Тема в разделе "MySQL", создана пользователем artoodetoo, 28 авг 2020.

  1. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.237
    Адрес:
    там-сям
    Помогайте парни. Мой мозг в пятницу просит пощады. Может быть пока формулирую задачу, решение вызреет. Короче, полагаюсь на эффект резинового утёнка. :)

    Есть:

    В каждый момент пользователю назначен какой-то уровень из таблицы
    levels(id, level_name, rank)
    и пользователь имеет ссылку вида users.level_id

    Уровни упорядочены по rank, чем он больше, тем "выше" уровень. Но, как обычно, не гарантированно, что rank прописан явно. Он по дефолту 0. Когда rank равен у двух записей, то порядок просто по id. Т.е. вывод по порядку роста уровня будет такой:

    Код (SQL):
    1. SELECT * FROM levels ORDER BY rank ASC, id ASC
    https://www.db-fiddle.com/f/wUDBMnQ9WeHu1CY6YuqmGd/0

    Требуется:

    Выбрать "предыдущий" или "следующий" уровень чтобы изменить ранг пользователя. Без грёбаных циклов, в один SQL запрос. Если уровень крайний, то допустимо получить "пусто" в результате, это не проблема.

    Если БЫ rank был гарантированно назначен и уникален, то формула была бы такой —
    уровень выше, чем уже назначенный пользователю уровень:

    Код (SQL):
    1. SELECT l.*
    2. FROM levels AS l,
    3.   (SELECT * FROM levels WHERE id = :user_level_id) AS ul
    4. WHERE l.rank > ul.rank
    5. ORDER BY l.rank ASC
    6. LIMIT 1
    Но если мы усложняем задачу дефолтовыми и неуникальными rank, то по-моему так:

    Код (SQL):
    1. SELECT l.*
    2. FROM levels AS l,
    3.   (SELECT * FROM levels WHERE id = :user_level_id) AS ul
    4. WHERE l.rank > ul.rank OR (l.rank = ul.rank AND l.id > ul.id)
    5. ORDER BY l.rank ASC, l.id ASC
    6. LIMIT 1
    Я прав или нет?
     
    #1 artoodetoo, 28 авг 2020
    Последнее редактирование: 28 авг 2020
  2. Дюран

    Дюран Активный пользователь

    С нами с:
    9 мар 2018
    Сообщения:
    256
    Симпатии:
    19
    А так не проще?:
    Код (Text):
    1. SELECT id,level_name
    2. FROM levels
    3. WHERE (rank > :user_old_rank ) OR
    4. (rank=:user_old_rank AND (id >:user_old_rank_id))
    5. ORDER BY levels.rank ASC, levels.id ASC
    6. limit 1
     
    #2 Дюран, 29 авг 2020
    Последнее редактирование: 29 авг 2020
  3. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.072
    Симпатии:
    1.237
    Адрес:
    там-сям
    @Дюран спасибо, это мой запрос, фактически.
    понимаешь, чтобы твоя версия заработала. надо сначала получить отдельным запросом тот самый SELECT * FROM levels WHERE id = :user_level_id , на который ты упростил мою версию )))

    в общем, эффект утёнка достигнут. пока писал, сам себе доказал верность выбранного пути.