2014-10-09 3 views
3

Моя страница PHP запрашивает таблицу файлов, и пользователи могут щелкнуть столбцы на странице, чтобы отсортировать по названию, дате, размеру, статусу и имени пользователя. Затем они могут щелкнуть по каждому файлу, чтобы просмотреть его на отдельной странице игрока.Поиск следующей/предыдущей строки в MySQL

Что я хотел бы сделать, это создать предыдущие/следующие кнопки в проигрывателе, чтобы перейти к предыдущему или следующему файлу , как указано на странице «Файлы». Это означает, что результаты могут быть упорядочены по любому из параметров, перечисленных выше.

За то, как дата, это довольно просто:

SELECT * FROM Files WHERE date > curdate ORDER BY date LIMIT 1 

Однако некоторые из других параметров вызывает у меня вопросы:

  • Как справиться со строками, как от имени загрузить пользователя?

  • Как я могу справиться с ситуациями, когда следующий элемент в отсортированном столбце имеет то же значение? Например, статус - это int между 0 и 3, и большинство файлов будут иметь статус 0. Если я сортирую по состоянию на странице «Файлы», он сначала перечисляет все файлы со статусом 0, затем статус 1 и т. Д. Поэтому, если мой текущий файл находится в середине 0 файлов состояния, как узнать, что следующий, который также имеет статус 0?

(PS Я знаю, что есть много потоков на эту тему, но я не видел, направленные на решение конкретных ситуаций выше.)

+0

есть много вопросов по аналогичной теме, с множеством ответов, которые на самом деле не работают. Вам удалось определить ключевую проблему упорядочивания нестандартных значений. «Трюк» заключается в том, чтобы заказать что-то уникальное ... ваш «главный» столбец (то, что пользователь сказал, что он хочет упорядочить предметы, а затем ваш секретный «второстепенный» столбец, который дает вам уникальный идентификатор строки «Трюк» состоит в том, чтобы использовать значения из строки «последний увиденный» для начала в «следующей» строке. Соответствующий индекс сделает это эффективным, может быть более эффективным, чем некоторые другие популярные подходы. – spencer7593

ответ

3

Q: Как я могу иметь дело со строками, как имя загружающий пользователь?

A: Точно так же вы имеете дело с датами и цифрами. Строки также «упорядочиваются».

В: Как я могу справиться с ситуациями, когда следующий элемент в отсортированном столбце имеет то же значение?

A: Точно так же вы будете иметь дело с повторяющимися значениями для дат, которые не являются уникальными. В дополнение к столбцу «major» sort вам нужен другой «младший» сортировочный столбец, который уникален, или комбинация «major» и «minor» вместе уникальна.

В идеале у вас должен быть PRIMARY KEY или UNIQUE KEY для столбца с нулевым значением, который может служить «младшим» порядком сортировки.

«Трюк» состоит в том, чтобы сохранить текущую позицию в списке, сохранив основные и второстепенные значения в строке «последний раз», а затем используйте эту информацию в запросе, чтобы получить «следующую» страницу.

WHERE t.major >= :last_seen_major 
     AND (t.major > :last_seen_major OR t.minor > :last_seen_minor) 
    ORDER BY t.major ASC, t.minor ASC 
    LIMIT 1 

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

Для получения максимальной производительности запроса вам понадобится индекс с ведущими столбцами (major, minor).

На основании вашего запроса, предполагая, что у вас есть id колонки, вы могли бы сделать что-то вроде этого:

SELECT f.* 
    FROM Files f 
WHERE f.date >= :last_seen_date 
    AND (f.date > :last_seen_date OR f.id > :last_seen_id) 
ORDER BY f.date ASC, f.id ASC 
LIMIT 1 

Чтобы заказать какой-либо другой колонке заменить f.date в WHERE и ORDER BY статей с чем-то еще , например f.name.


Менее производительный альтернатива

Другой очень популярный подход заключается в использовании «смещение» в предложении LIMIT.

Вначале румянец, кажется, является изящным решением, но у него есть некоторые проблемы.

Вы можете сделать:

ORDER BY major ASC, minor ASC LIMIT 41,1 

Для «следующего» строки, то увеличиваем смещение на 1

ORDER BY major ASC, minor ASC LIMIT 42,1 

Одна из проблем, с этим подходом, если строка вставляется в диапазоне уже увиденные строки, «следующий» запрос вернет ту же строку. Поскольку 41-я строка была теперь 42-й строкой. Если кто-то удалит строку, «следующий» запрос пропустит строку. И я не хочу жить с таким дефектом в моей функции «получить следующую строку». И этот подход по-прежнему должен отслеживать позицию в списке, но, неся дополнительное смещение, которое на самом деле не является частью строки.

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

+0

Спасибо, это было очень полезно Честно говоря, я не был полностью уверен, как использовать переменные связывания, поэтому я удалил двоеточия и ссылался на текущее значение переменной, и это отлично работало при тестировании. Мой код выглядит примерно так: 'SELECT f. * FROM Files f WHERE f.date> = $ date И (f.date> $ date OR f .id> $ file_id) ORDER BY f.date ASC, f.id ASC LIMIT 1' И для поиска предыдущего файла это практически то же самое, но с> обратным и сортировкой по убыванию. – mwoods