Я хочу отобразить галерею изображений, и на странице просмотра должна быть возможность взглянуть на кучу миниатюр: текущее изображение с двумя предыдущими записями и двумя следующими.
Проблема получения двух next / prev в том, что я не могу (если не ошибаюсь) выбрать что-то вроде MAX (id) WHERE idxx.
Любая идея?
примечание: конечно, идентификаторы не следуют, поскольку они должны быть результатом нескольких экземпляров WHERE.
Спасибо Маршалл


Если вас просто интересуют предыдущая и следующая записи по идентификатору, не могли бы вы просто иметь предложение where, которое ограничивает WHERE id = xx, xx-1, xx-1, xx + 1, xx + 2, используя несколько предложений WHERE или используя В КОТОРОЙ ?
если ваши идентификаторы непрерывны, вы можете сделать
where id >= @id-2 and id <= @id+2
В противном случае, я думаю, вам придется выполнить union 3 запроса, один для получения записи с заданным идентификатором, а два других возятся с top и order by, как это
select *
from table
where id = @id
union
select top 2 *
from table
where id < @id
order by id desc
union
select top 2 *
from table
where id > @id
order by id
Производительность будет не такой уж плохой, поскольку вы не получаете массивные наборы данных, но она не будет хорошей из-за использования union.
Если вы обнаружите, что производительность начинает быть проблемой, вы можете добавить столбцы для хранения идентификаторов предыдущего и следующего элементов; вычисление идентификаторов с помощью триггера или ночного процесса или чего-то еще. Это будет означать, что вы выполняете жесткий запрос только один раз, а не каждый раз, когда он вам нужен.
NB: «TOP 2» - это проприетарный синтаксис Microsoft / Sybase, не поддерживаемый MySQL. Вместо этого MySQL использует необязательное предложение LIMIT, которое появляется после предложения ORDER BY.
Вам придется простить имена переменных в стиле SQL Server, я не помню, как MySQL выполняет именование переменных.
SELECT *
FROM photos
WHERE photo_id = @current_photo_id
UNION ALL
SELECT *
FROM photos
WHERE photo_id > @current_photo_id
ORDER BY photo_id ASC
LIMIT 2
UNION ALL
SELECT *
FROM photos
WHERE photo_id < @current_photo_id
ORDER BY photo_id DESC
LIMIT 2;
В этом запросе предполагается, что у вас могут быть несмежные идентификаторы. Однако в конечном итоге это может стать проблематичным, если у вас много фотографий в вашей таблице, поскольку TOP часто оценивается после, весь набор результатов был получен из базы данных. YMMV.
В сценарии с высокой нагрузкой я, вероятно, использовал бы эти запросы, но я бы также регулярно их прематериализировал, чтобы каждая фотография имела столбец PreviousPhotoOne, PreviousPhotoTwo и т. д. Это немного больше обслуживания, но оно хорошо работает, когда у вас много статических данных и вам нужна производительность.
Я думаю, что этот метод должен работать нормально для несмежных идентификаторов и должен быть более эффективным, чем использование UNION. currentID может быть установлен либо с использованием константы в SQL, либо путем передачи из вашей программы.
SELECT * FROM photos WHERE ID = currentID OR ID IN (
SELECT ID FROM photos WHERE ID < currentID ORDER BY ID DESC LIMIT 2
) OR ID IN (
SELECT ID FROM photos WHERE ID > currentID ORDER BY ID ASC LIMIT 2
) ORDER BY ID ASC
Разве вы не должны использовать OR вместо AND для предложения WHERE?
Это могло бы работать в идеальном мире, где у вас есть непрерывный столбец идентификаторов, но иногда возникают пробелы (неудачные вставки, удаления и т. д.). Я обнаружил, что лучше использовать TOP x в сочетании с WHERE, чтобы получить самые близкие.