Выборка каждой n-ой строки

MagicGTS

Новичок
Выборка каждой n-ой строки

Никак не могу сообразить, как сделать, чтобы не тормозило.
Есть таблица вида: id, name, .....
Нужен вывод постранично, и тут есть засада. Для облегчения жизни юзера, решил скрипту передавать не номер страницы, где находится юзер, а id элемента, который должен находится на этой странице. Вот тут и наступает самое интересное.
Условия к выводу у меня довольно просты, поле name выводится отсортированное по алфавиту. Для начала считаю двумя запросами количество записей, и количество записей перед той что "нужно показать юзеру". Эта часть считается почти мгновенно. А теперь нужно сгенерить ссылочки на странички, в которых должен фигурировать id записи. Вот тут я не придумал ничего лучше такого убожества:
PHP:
//$t_page общее количество страниц полученное ранее
//$dpp количество записей, выводимое пользователю (я использую 60)
for($i=0;$i<$t_page;$i++) 
{	
	$query_str="SELECT id from table order by name LIMIT ".($i*$dpp).",1;";
	$query=mysql_query($query_str,$db);
	//Тута выдаём полученные id
}
В итоге при количестве записей около 8к сервер умирает секунд на 7-10, виной конечно лобовая реализация задуманного.
Идеальным решение будет выборка одним запросом, но с "фильтром", чтобы выводил каждую n-ую запись из запрошенных. Работающих решений не придумал, а похожего не удалось найти (может, плохо искал)?
 

svetasmirnova

маленький монстрик
Я не поняла. Ты же name из базы забираешь и потом выводишь, так?
 

bkonst

.. хочется странного?...
Может, чем устраивать себе кучу проблем, сделать так, чтобы скрипт мог принимать и номер элемента, и номер страницы?
 

MagicGTS

Новичок
Мне нужно получить каждый n-ый элемент из выборки в 8000 элементов отсортированых по имени.
к примеру в базе есть:
name1
name2
name3
.....
name8000
Тока оно в базе не подряд лежи, а надо сортировать. Вот из этого набора мне нужна каждая десятая запись, типа чтобы было:
name1
name10
name20
.....
При этом обрабатываю не все записи таблици, я делаю фильтрацию по другим полям. Вобщем из базы нужно выбрать по условию пару тысяч записей, отсортировать, и из этого набора забрать только каждую n-ую.
Для тех кто не понял зачем оно мне. Если честно, я не ставил вопрос: предложите механизм постраничного вывода результатов. Мне нужно решение описанной проблемы. Надеюсь теперь задача доходчива разъяснена?
 

tf

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

bkonst

.. хочется странного?...
SQL такого штатно не позволяет. Можно "порядковые номера" записей (которые будут обновляться при удалении строк, так чтобы не возникале пропусков) и выбирать записи, номер которых не имеет остатка от деления на размер страницы. Подход спорный и вызовет проблемы в будущем; к тому же - не будет работать при условии фильтрации записей.

Насчет того, что вам не нужны советы по тому, как реализовывать страничный вывод: при нормальном подходе к проектированию "странных" задач, как правило, не возникает. Увы, я так и не понял, зачем формировать ссылки на страницы именно по номеру первого элемента страницы.
 

MagicGTS

Новичок
Автор оригинала: bkonst
Увы, я так и не понял, зачем ормировать ссылки на страницы именно по номеру первого элемента страницы.
А это чтобы ссылка указывала на максимально точно заказанную страницу. Если делать стандартно, то при значительном увеличение размеров данных, ссылки на такие страницы будут сильно не соответствовать желаемому. Есть море конференций и других ресурсов, у которых постраничный вывод именно такой. Ищешь что-нибудь в поиске, кликаешь на ссылку и попадаешь, к примеру, на 4 страницу обсуждений. Но на ней нет того, что показывает поисковик. Ищем на соседних страницах, но и там этого нет. В итоге после некоторых напрягов находим искомое на 30-40 странице. В моем решение есть плюс, нужно очень сильно и неравномерно заполнить таблицу, чтобы страницы сильно разбежались. А какой номер элемента должен фигурировать на странице не имеет значения, просто для простоты генерации я ставлю первый элемент, но лучше наверно тот, что в середине.
Вариант с собственоручно накручеными "индексами", как ты предлагаешь, пробывал, но эфект от этого не очень получился, но видимо опять накосячил с реализацией. Нужно всетаки постараться без таких наворотов.
 

bkonst

.. хочется странного?...
А-а-а. Идею понял... Да, интересный подход.

Ну, в конце концов, если страниц должно выводиться немного (большая часть форумов показывает только ссылка 3-4 страницы от текушей), и на странице не очень много элементов, то можно просто "в лоб" выбрать все элементы этих страниц (порядка сотни идентификаторов) и выбрать нужные уже при обработке результатов запроса.
 

MagicGTS

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

bkonst

.. хочется странного?...
Можно поиграться с robots.txt...

Например, для каждого сообщения создать постоянную ссылку, ведущую на это (и только на это) сообщение и запретить индексацию поисковиками тредов. Тогда результаты поисковиков будут выбрасывать на конкретное сообщение, а уж оттуда не так сложно вывести пользователя в нужное место треда.
 

MagicGTS

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

svetasmirnova

маленький монстрик
MagicGTS
Ответь на мой вопрос, please:
>Ты же name из базы забираешь и потом выводишь, так?
 

MagicGTS

Новичок
При построение ссылок name мне не нужен, но по нему нужно обязательно сортировку делать, да ещё его в условиях выборки использую (фильтры по алфавиту). Тока не пойму, разве в приведенных описаниях проблемы и моего решения не ясно что для ссылок name ваще как выходные данные не нужен?
 

svetasmirnova

маленький монстрик
name-то не нужен, но что тебе мешает выбрать на одну строку больше и прихвать к ней id?
Тем более, что:
>Эта часть считается почти мгновенно.
 

uninside

Новичок
сервер какой у тебя? если 5.1, то можешь использовать
SELECT.... WHERE id IN (1,10,20,30,40);
 

Profic

just Profic (PHP5 BetaTeam)
Для данного случая могу предложить примерного такую, ранее уже озвученную на этом форуме, последовательность запросов:
[sql]
set @pos := 0;
select * from (select *, (@pos := @pos + 1) % 10 as posmod from tbl) as temp where posmod = 1;
[/sql]
Данный запрос будет работать c MySQL 4.1+. Переделку этого запроса для работы с MySQL 4.0 оставляю в качестве домашнего задания.

-~{}~ 20.12.05 18:42:

uninside
а что такого появилось в 5.1, из-за чего твой запрос отработает как надо автору топика?
 

uninside

Новичок
Хе, ошибочка вышла, IN с версии 4.1.0 :)

да, я думал что ему id надо перечислять. надо выспаться.
 

MagicGTS

Новичок
Profic
Агромное спасибо!
Я тоже пытался сделать так, но не допер запихать подсчет и первичную выборку в подзапрос как таблицу. Из-за этого решение с переменными мускла всё время неработало как я не изворачивался. А тут получается завуалированое использование "временной" таблици.
Теперь построение списка страниц проходит молниносно!
 
Сверху