Получить две следующие и две предыдущие записи в одном запросе SQL - PullRequest
2 голосов
/ 02 января 2009

Я хочу отобразить галерею изображений, и на странице просмотра можно будет просмотреть несколько миниатюр: текущее изображение, обернутое двумя предыдущими записями и двумя последующими.

Проблема получения двух следующих / предыдущих файлов заключается в том, что я не могу (если не ошибаюсь) выбрать что-то вроде MAX (id) WHERE idxx.

Есть идеи?

примечание: конечно, идентификаторы не следуют, поскольку они должны быть результатом нескольких экземпляров WHERE.

Спасибо Marshall

Ответы [ 4 ]

4 голосов
/ 02 января 2009

Вам придется простить имена переменных в стиле 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 и т. Это немного больше обслуживания, но оно хорошо работает, когда у вас много статических данных и вам нужна производительность.

3 голосов
/ 02 января 2009

Я думаю, что этот метод должен хорошо работать для неконтролируемых идентификаторов и должен быть более эффективным, чем использование 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
3 голосов
/ 02 января 2009

если ваши идентификаторы непрерывны, вы можете сделать

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.

Если вы обнаружите, что производительность начинает вызывать проблемы, вы можете добавить столбцы для хранения идентификаторов предыдущего и следующего элементов; вычисление идентификаторов с использованием триггера или ночной процесс или что-то. Это будет означать, что вы выполняете сложный запрос только один раз, а не каждый раз, когда он вам нужен.

0 голосов
/ 02 января 2009

Если вы просто интересуетесь предыдущей и следующей записями по id, не могли бы вы просто иметь предложение where, которое ограничивает WHERE id = xx, xx-1, xx-1, xx + 1, xx + 2, используя несколько WHERE пункты или используя WHERE IN?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...