определяемый пользователем порядок записей в таблице

neko

tеam neko
определяемый пользователем порядок записей в таблице

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

вобщем мы тут чуть-чуть пообсуждали и пришли к 2ум приемлемым вариантам, которые оба сводятся к тому, чтобы завести еще один столбец для сортировки (предположим он называется x).

первый вариант, для интерфейсов где есть операции "выше"/"ниже". при вставке записи делать x = max(x) + 1, а при передвижении просто менять местями значения x. в принципе это терпимый вариант, до тех пор пока пользователь не начинает "вставлять" записи (например посредством drag'n'drop)

второй вариант использовать числа с плавающей точкой.
x, точно так же = max(x) + N для новых записей.
чтобы вставить c между a и b: c.x = a.x + (b.x - a.x)/2.
т.е. вставляем по середине.
поскольку через некоторое время тут могут возникнуть проблемы с точностью, разность (b.x - a.x) служит индикатором того, когда столбец x надо заново заполнить.
и сооответственно N устанавливается от в зависимости от объема перемещений и кол-ва записей.

все это будет работать но в целом не слишком красиво.

хотелось бы услышать какие еще есть идеи
 

Стас

Троечник
neko
Я правильно понял: речь идет о том, чтобы пользователь мог самостоятельно определять ORDER BY?
Я сделал так (отрывок кода, дабы не пустословить. Файл bbft.php)
PHP:
<tr bgcolor="#666666">
<td valign="top">
<a href="bbft.php?order=<?php echo urlencode("id");?>">ID<?php if ($OrderBy == "id") { ?><?php echo (@$HTTP_SESSION_VARS["bbft_OT"] == "ASC") ? - : ((@$HTTP_SESSION_VARS["bbft_OT"] == "DESC") ? + : "") ?><?php } ?></a>
</td>
Поясню: В заголовках колонок рисую те самые "Выше/ниже". Когда переходим по сортировке, то в начале делаем ORDER BY и записываем для этого пользователя порядок сортировки (в куки там...сессии).
Пы.Сы.
Пишу и сам понимаю, что, видимо "не по делу пишу". Ну так я вопрос понял. Извините за флуд.
 

gfd

Guest
Теоретические размышления(для второго варианта):

Имеем f(x1,x2)=x1+y(x1,x2), где у в приведенном варианте

y(x1,x2)=(x2-x1)/2

Фактически точность в этом случае зависит от функции
y(x1,x2) Если построить график, то легко увидеть, что y(x1,x2)=(x2-x1)/2 падает слишком быстро и даже при N=9999 предела точности достигнет достаточно легко даже, при поле x - float(4.9) (x1 - будет уже около 5000, второе 2500 и т д, аэто на мой взгляд не слишком рационально) и лучше тогда уже использовать y(x1,x2)=(x2-x1)/1.5, к примеру :), хотя скорее всего - это будет что-то нелинейное.

Думаю, в каждом конкретном случае нужно определиться с параметрами использования таблицы(как часто вставляються записи между другим, сколько их ожидаеться всего) и поэкспериментировать с каким-нибудь построителем графиков - порисовать разные ф-и и выбрать подходящую(если помните хорошо мат анализ - можно и без грфиков рассчитать:))

Извините, за голое теоретизирование - на практике у меня такой потребности не возникало.
 

vafel

Новичок
ну точность то обеспечить непроблема, правда надо поковырятся в bcmath или gmp.
Я проблему сортировки реализую селектором где пользователь двигает, потом блокировка таблицы и вариант 1.
 

neko

tеam neko
> ну точность то обеспечить непроблема, правда надо поковырятся
> в bcmath или gmp.
это малость того, не в кассу
bcmath тут не при чем, а ноги проблемы с точностью растут из того что преполагалось использовать стандартные float/double
единственные 2 способа ее обеспечить, это либо использовать постоянно растущее поле выделяемое под такое "число", либо время от времени перестраивать реализацию с плавающей точкой.

> x - float(4.9) (x1 - будет уже около 5000, второе 2500 и т д,
> аэто на мой взгляд не слишком рационально)

вот это я непонял, можно объяснить?
если что -- float это 1E+-37, с точностью до 6ти знаков

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

Crazy

Developer
маленькое замечание: есть ровно 0 причин использовать в данном случае числа с плавающей точкой.
 

neko

tеam neko
желательно поподробнее?
меня в частности интересуют вопросы вставки записи в середину
 

gfd

Guest
> x - float(4.9) (x1 - будет уже около 5000, второе 2500 и т д,
> аэто на мой взгляд не слишком рационально)

вот это я непонял, можно объяснить?
если что -- float это 1E+-37, с точностью до 6ти знаков
Виноват невнятно выразился(имелось ввиду не x, а дельта x, но это все равно выглядит как бред - напишу по другому):

Допустим при N = 10000, мы можем вставить Y записей между a и b, пока не достигнем предела точности. Так вот, если мы решим, что нам этого мало и может возникнуть потребность вставлять до 10*Y записей между двумя существующими то N придется увеличить на несколько порядков - значит мы меньше сможем добавить записей в таблицу(в конец).
Если y(x1,x2) падает быстро то 1E+-37 может быстро "съесться" до, скажем, 1000000(возможность добавления новых записей в конец), но при этом мы будем иметь возможность вставлять тысячи записей между двумя добавленными одна за одной.

Это все вопросы пределов применимости способа.

P. S. Понятия не имею на кой могла бы понадобиться такая здоровенная таблица, но мы же теоретизируем:)
 

fixxxer

К.О.
Партнер клуба
ну уж не знаю, как может не хватить 64 бит (bigint). ну если теоретизировать - можно сделать два поля. или три. или больше.

а float использовать действительно глупо. получаем те же 64 бита и дополнительно кучу проблем.
 

kruglov

Новичок
Записей в таблице миллион, и записываем мы в нее тыщу раз в секунду? Нет? Тогда какие проблемы делать
UPDATE ... x=x+1 WHERE x>kuda ?
 

neko

tеam neko
fixxxer
Crazy
понятно
т.е. вы предлагаете тоже самое, но при том отмечаете, что числа не обязательно должны быть фракциональными, если взять достаточный шаг
согласен

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

Crazy

Developer
neko, я вижу один разумный вариант:

1. Нам нужно упорядочить записи, следовательно нам нужно последовательность, в соответствии с которой мы их будем упорядочивать.
2. Простейшей последовательностью, которую мы можем использовать, является последовательность целых чисел.
3. Чтобы уменьшить частоту переназначения элементов последовательности при вставке, мы можем изначально назначать их с пропусками.

Серьезной альтернативы этому подходу я не вижу.

Есть смешные нюансы. Так, используя БОЛЬШОЙ... нет... ОЧЕНЬ БОЛЬШОЙ шаг мы можем вообще отказаться от перенумерации. К примеру, выдавя коды с шагом в миллион.

Не хватает битиков? Сериализуем число в строку символов. По основанию 62, к примеру.

Если есть принципиально иные идеи, то их было бы крайне интересно услышать и обсудить.
 

neko

tеam neko
> Не хватает битиков? Сериализуем число в строку символов. По
> основанию 62, к примеру.

да, это вариант номер три
причем это можно делать используя, какие-нибудь блобы и полные 256 вариантов для знака ;-)
соотв. там будет работать уже другое сравнение и можно "точность" увеличивать бесконечно ;-)

> Если есть принципиально иные идеи, то их было бы крайне
> интересно услышать и обсудить.

принципиально иная идея есть
я прошу отнестись к ней с состраданием ;-)
суть идеи в том, чтобы в базе хранить doubly linked list
соответственно триггеры на удаления и sp на вставку чтобы это дело поддерживать
и materialized view, чтобы выборка вообще была выборкой, а не перебором записей :Р
это уродство конечно, полное
но вот знаете что.
это единственный вариант который не делает вообще никаих предположений по поводу потенциальной емкости.
т.е. на мой взгляд наиболее "чистый", хотя и наименее реляционный

есть еще есть у кого-то мысли, просьба высказываться
 

Мутник

Новичок
А нельзя иметь изначально шаг в колонке ordering 10. у тебя получается такая штука: 0, 10, 20, 30, 40

если хочешь вставить между 10 и 20 делаешь так: 0, 10, 20(новая запись) а всем остальным даешь + 10 (т.е. апдейтом простым). Вернее, сначала апдейтишь WHERE `ordering` > 20, а потом вставляешь.

Или, я неправильно понял вопрос.
 

Crazy

Developer
Мутник, выполнение update над ВСЕМИ (при вставке в начало) строками по индексируемому полю -- это не самая светлая мечта.
 

TAHK

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

kruglov

Новичок
Если приходится делать update над всеми записями, и это напрягает систему, то что-то не в порядке с логикой хранения данных. Почему такие большие списки?

Было сказано, что это "плейлисты". Кому нужен плейлист из многих тысяч записей? А если эти "мириады" записей получаются потому, что в таблице мы храним все плейлисты всех юзеров, деля их по "user_id", то нам все равно не нужно обновлять всю таблицу, а только по этому user_id.

Потом, если вставка в начало является частой операцией, мы можем и отрицательные номера выдавать.
 

Crazy

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

Если проблемы нет, то пора расходиться... ;)
 

kruglov

Новичок
Проблемы у него нет, одно "умозрение":

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