Портал г.Новоселица Черновицкой области, Украина; Портал м.Новоселиця Чернівецької області, Україна

Навигация в php+mysql: нумерация и определение позиции

Столкнулся с этой проблемой: создание навигации в php, используя данные mysql. Проблема проявилась тогда, когда я ужесточил требования от навигации, а именно: переход на страницу многостраничного списка, скажем, ответов форума, на которой находится ответ с определенным id.

Для решения нужно было:

а) определить количество страниц по N ответов на странице. Это делается легко: после запроса определяем количество записей и нехитро определяем количество страниц:

$pozstrok = ($el !== false)?mysql_num_rows($el):0; $pages = ($pozstrok == 0)?0:ceil($pozstrok / $poskolko);

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

Оставалось или отказаться от идеи, или сильно думать.

В сильнодумающем процессе, перелопачивая тонны интернет-ресурсов, нашел ответ, как нумеровать строки с помощью пользовательских переменных mysql.

SET @t:=1; SELECT *, @t:=@t+1 FROM baza;

Переменная получает новое значение прямо в теле запроса.

На этом основании и возникла идея: поставить метку напротив нужной записи. И если во время проставления этой метки засечь значение счетчика, то сразу получаем номер строки нужной записи. Например:

IF(baza.kod = id, @t, 0) as votono

- а потом вычислить максимум по 'votono'. В реалиях идея вылилась вот в такую формулу:

SET @t:=1, @tk=0; SELECT @tk:= ( (@t:=@t+1)*0 + IF(baza.kod=id, @t, @tk) ), baza.* FROM baza;

после чего запрос

$el1 = mysql_query("SELECT @tk"); $r = mysql_fetch_array($el1);

возвращает номер строки нужной записи. А формула:

$page = ceil($r[0] / $poskolko) - 1;

даёт нужную страницу. Выборка страницы происходит без помощи LIMIT:

if ($pozstrok >= $page*$poskolko) @mysql_data_seek($el, $poz*$poskolko); //переходим на первую запись страницы for ($i=0; $i < $poskolko; $i++) { //выбираем N ответов };

В процессе поиска решения обнаружились такие проблемы:

При добавлении сортировки ORDER BY счетчик @t в некоторых запросах не давал себя прочесть, если он был оформлен как поле (@t:=@t+1 as pole1). Разместил в выражение - пока проблем не наблюдаю.

Более серьезная проблема: при добавлении выборки из другой таблицы - вообще ужас. ORDER BY срабатывал по другому, полностью нарушая работу счетчика, поэтому пришлось подворовывать поля подзапросом:

SELECT @tk:= ( (@t:=@t+1)*0 + IF(baza.kod=id, @t, @tk) ), baza.*, (SELECT baza2.pole FROM baza2 WHERE baza.kto = baza2.kod) as pnaim FROM baza;

Таким образом удалось выкрутиться и получить необходимый результат.

Благодаря этой метке, которая в нужное время принимает значение счетчика строк, удалось и перейти на страницу, на которой нужная запись, и подсвечивать её, т.е. внедрить поиск записи в навигацию. Мне самому понравилось.

Будь я разработчиком mysql, я бы ввел хотя бы счетчик выводимых после сортировки строк.

dnepr, 03.06.09г.