Выбор следующего элемента из отсортированного списка

Bitterman

Новичок
Выбор следующего элемента из отсортированного списка

Проблема в следующем:
В таблице хранятся изображения (ессно не сами картинки, а их параметры). У каждой из них есть рейтинг. Мне требуется показывать их отсортированными по рейтингу. С выводом на экран списка проблем нет, затык у меня произошел при выводе картинок на экран по отдельности. Соответственно, у нас есть ID текущей картинки, надо каким-то образом получить ID следующей (или предыдущей, что в данном случае непринципиально). Как одним запросом получить следующую картинку я не знаю. Единственный вариант, который пришел в голову - хранить в сессии массив ID всех картинок, уже отсортированный и выбирать из него, но это как-то выглядит коряво. Кто-нить что-нить подскажет?

Таблица Image:

ID int(11)
Title varchar(255),
Rating int(11),
TotalVotes int(11)
 

HraKK

Мудак
Команда форума
Bitterman
хранить в сессии массив ID всех картинок
Не лучший выбор потому что человек получивший прямую ссылку не увидит "назад" и "вперед"

-~{}~ 05.11.07 16:42:

Апокалипсис
ORDER BY Rating
 

Bitterman

Новичок
Каким образом идёт выборка?
SELECT *, ROUND(Rating/TotalVotes, 2) as Rate FROM Image ORDER BY Rate DESC
Не лучший выбор потому что человек получивший прямую ссылку не увидит "назад" и "вперед"
Ну можно каждый раз проверять наличие массива и если его нет - загружать. Но этот вариант мне и самому не нравится.
 

Фанат

oncle terrible
Команда форума
Bitterman
ну, классический ответ -= еще два запроса, которые получают вперед и назад. большь-меньше
 

Gas

может по одной?
ну написать то их можно, но они уродливые и тоже сканят всю таблицу. (шёпотом так: может просто завести отдельное поле rate и не мучаться?)
 

WDStalker

Новичок
Bitterman может так
первый запрос
SELECT *, ROUND(Rating/TotalVotes, 2) as Rate FROM Image ORDER BY Rate DESC
получив Rate, второй запрос
SELECT *, ROUND(Rating/TotalVotes, 2) as Rate FROM Image WHERE Rate<{$Rate} ORDER BY Rate DESC LIMIT 1
и тд
 

Bitterman

Новичок
WDStalker
Нет. Так как в твоем варианте мы пропускаем элементы, у которых рейтинг такой же как и у текущего, если же вместо знака < поставить <= , то рискуем получить бесконечный цикл.
Gas
шёпотом так: может просто завести отдельное поле rate и не мучаться?
Честно говоря не понял, чем поле Rate облегчит мне жизнь.
 

Krishna

Продался Java
Bitterman
Ну может так? :)
[sql]SELECT id from (SELECT title,id FROM image WHERE rating>=(select rating from image where id=$current_pic_id) and id<>$current_pic_id) WHERE id>$current_pic_id order by rating asc, id asc limit 1[/sql]
- следущая, при условии, что id - primary key. Правда, производительность под большим вопросом :D
 

Bitterman

Новичок
Krishna
Негде сейчас проверить, но, по-моему, тоже нет :(
Для случая, когда в последовательности

id | rate
-----------
1 | 4
2 | 4
3 | 4

текущий элемент - 2, твой запрос выберет 1 и 3, и из них по лимиту - 1. Для элемента же 1, выберутся 2 и 3 и по лимиту - 2 и мы пойдем на второй круг :(.
Похоже, исключительно MySQL проблему не решить. Надо придумывать что-то еще.
 

Krishna

Продался Java
текущий элемент - 2, твой запрос выберет 1 и 3
Запрос выберет 3.
З.Ы.
(Теперь, после того, как я его поправил :) )
Для элемента же 1, выберутся 2 и 3 и по лимиту - 2 и мы пойдем на второй круг .
На какой еще "второй круг". Выберется 2, а что по-твоему должно быть выбрано?

-~{}~ 06.11.07 00:38:

А сорри, понял о чём ты в первом случае.
Ну так проще простого, блин, ща поправим.
 

Bitterman

Новичок
Запрос выберет 3.
Опять-таки повторюсь, что проверить сейчас негде, но, по-моему, все-таки запрос выберет 1.
На какой еще "второй круг". Выберется 2, а что по-твоему должно быть выбрано?
Зацикливание произойдет. При текущем элементе 2 следующим будет выбираться элемент 1, а при текущем элементе 1 - элемент 2. До третьего очередь никогда не дойдет.

--------------------------------------------------------------------------------------------

Посмотрел поправки - увы, так тоже не катит. Твой запрос подходит только при условии, что каждый элемент с бОльшим id имеет бОльший (или такой же) рейтинг.
 

Krishna

Продался Java
Ну, вот щас вроде в порядке :)
Голова уже туго варит)
Не люблю на ночь думать :(
 

Bitterman

Новичок
Честно говоря, не понял, что изменилось в запросе в последний раз :(. В текущем варианте меня смущает условие WHERE id > $current_pic_id . Почему id следующего элемента должен быть больше текущего?
Голова уже туго варит)
Не люблю на ночь думать
Согласен, поэтому предлагаю перенести дальнейшие прения на завтра :)
 

Mr_Max

Первый класс. Зимние каникулы ^_^
Команда форума
Bitterman
Может "да ну его в лес" этот один запрос?
и UNION? :)
 

Krishna

Продался Java
Честно говоря, не понял, что изменилось в запросе в последний раз . В текущем варианте меня смущает условие WHERE id > $current_pic_id .
Как раз оно добавилось.

Почему id следующего элемента должен быть больше текущего?
Потому, что в предыдущем подзапросе, из которого мы извлекаем этот мы убрали все картинки с рейтингом ниже, чем у заданной картинки. Я предлагаю делать двойную сортировку - сначала по рейтингу, потом по ПК - id. То есть, если, например считать, что если у пяти картинок одинаковый рейтинг с текущей (id=26), то сортировать их надо так: {Те, что rate < 4} ... (id=15 rate=4), (id=26 rate=4), (id=118 rate=4), (id=324 rate=4) ... {Те, что rate > 4}

Mr_Max
А чем поможет UNION?


Вообще, я ступил. Надо применить GROUP BY и MIN :)


PHP:
 SELECT MIN(id) FROM image  WHERE  id <> $current_pic_id GROUP BY rate HAVING rate=> (SELECT rating
FROM image
WHERE id = $current_pic_id ) ORDER BY rate ASC LIMIT 1
Кажется, этот вариант тоже рабочий и при этом быстрее :)
Но убедиться надо завтра :)

-~{}~ 06.11.07 01:34:

Интересный глюк, ббкод <sql> не хочет работать в этом посте :)
 

Gas

может по одной?
Честно говоря не понял, чем поле Rate облегчит мне жизнь.
всё имхо: облегчит тем что: 1) запросы на получение next/prev будут более прозрачными; 2) производительность должна быть ощутимо выше (если ключ навесить) по сравнению с order и group по вычисляемому значению; 3) обновление этого поля осуществляется в том же запросе что и полей Rating/TotalVotes, никаких лишних телодвижений.

Ну а текущая задача интересна с академической точки зрения, вон Krishna на гора какие весчи выдаёт, но на практике производительность может оказаться неудовлетворительной.
 
Сверху