Jump to content
  • 0

(MySQL) Фиктивное изменение позиции строки в таблице


LokiDi L0ck
 Share

Question

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

Т.е., если имеется таблица users:

 id | name |
1 Вася
4 Петя
2 Игорь

То, выводилась она соответственно: Вася, Игорь, Петя.

Первая мысль создать новый столбец, например "position" и хранить в н?м число, по которому будет производиться сортировка.

 id | name | position
1 Вася 1
4 Петя 2
2 Игорь 3

Теперь, если пользователь на сайте хочет, чтобы Игорь был самым первым, кажется достаточно было бы изменить position Игоря на 1, Васи на 2, Игоря на 3. Но это глупо, т.к. получается большая нагрузка на сервер, при тысячах записей.

Потому, как вариант, можно вычислять между какими строками должна быть перемещаемая, и изменять е? "position" на среднее арифметическое между предыдущей и настоящей строками.

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

Если кто сталкивался, прошу поделиться логикой :)

Ссылкам по теме тоже буду рад :), - по гуглу пока ничего не наш?л.

Link to comment
Share on other sites

11 answers to this question

Recommended Posts

  • 0

хорошая тема

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

Но все же интересно каким образом лучше все это организовать.

на ум приходит пока только создание дополнительной таблицы, в которой два столбца

personid | position

personid - внешний ключ

position - позиция

я не уверен, но вроде UPDATE меньшей таблицы должен меньше нагружать сервер.

среднее арифметическое вариант хорош, но ИМХО не идеален и не элегантен :)

Link to comment
Share on other sites

  • 0
я не уверен, но вроде UPDATE меньшей таблицы должен меньше нагружать сервер.

Да верно, в поисках я наталкивался на такое решение задачи. И люди оным пользуются, но в разумных пределах.

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

Года два назад я наталкивался на тему логики контроля позиций так, чтобы номер позиции всегда находился в разумных пределах, но тогда не придал этому значения, соответственно и не сохранял :/

Прид?ться придумывать велосипед.

p.s. Хотя, в случае с расч?том среднего арифметического, можно в конце каждой недели (ночью) кроном вызывать скрипт, который будет перерасчитывать позиции строк на нормальные целочисленные. Таким образом нагрузка будет производиться всего один раз когда базу никто не использует, а если при этом ещ? использовать и дополнительную таблицу, то нагрузка спадает в разы.

p.p.s.

среднее арифметическое вариант хорош, но ИМХО не идеален и не элегантен

В сравнение с обновлением всей дополнительной таблицей, тут изменяется всего одно поле, одной строки =) Мне кажется это красивым решением, но только после того, как обдумаю логику)

Link to comment
Share on other sites

  • 0
Года два назад я наталкивался на тему логики контроля позиций так, чтобы номер позиции всегда находился в разумных пределах, но тогда не придал этому значения, соответственно и не сохранял :/

А очень даже зря Вы так поступили :)

p.s. Хотя, в случае с расч?том среднего арифметического, можно в конце каждой недели (ночью) кроном вызывать скрипт, который будет перерасчитывать позиции строк на нормальные целочисленные. Таким образом нагрузка будет производиться всего один раз когда базу никто не использует, а если при этом ещ? использовать и дополнительную таблицу, то нагрузка спадает в разы.

Все равно извращение :)

p.p.s.
среднее арифметическое вариант хорош, но ИМХО не идеален и не элегантен

В сравнение с обновлением всей дополнительной таблицей, тут изменяется всего одно поле, одной строки =)

я имел ввиду, что постоянно среднее арифметическое находится не будет (есть определенный предел, хоть и очень большой). но если делать так как написано выше, то вобщем более менее приемлемый вариант, но все равно извращение :)

Link to comment
Share on other sites

  • 0
я имел ввиду, что постоянно среднее арифметическое находится не будет (есть определенный предел, хоть и очень большой)

Да, именно проблему с пределом я и хочу обойти =) Как решение сломя голову - использовать крон, для перерасч?та) Т.к. вс? делается на автомате, нагрузка минимальна и контролировать дальнейшую работу такого решения не надо, считаю это неплохим вариантом))

...только на первое время %)

Link to comment
Share on other sites

  • 0

Пересчет по ночам хотя и хорош, но никак не виден пользователям. Т.е. они сами меняют свою позицию, а изменения видны только утром. Лучше всего наверное выделить позицию в отдельную таблицу и обновлять только ее.

Как вариант - использовать метод пузырька. Каждый пользователь вводит некое число, чем оно больше, тем выше поднимается. Тогда пересчет позиции не нужен, требуется только сортировать по условному числу. Но это опять несет некоторые неудобства.

Link to comment
Share on other sites

  • 0
Т.е. они сами меняют свою позицию, а изменения видны только утром. Лучше всего наверное выделить позицию в отдельную таблицу и обновлять только ее.

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

 id | name | position
4 Петя 0.0015
1 Вася 0.000245
2 Игорь 0.02

Перерасч?т означает, что скрипт пронумерует их снова как:

 id | name | position
4 Петя 2
1 Вася 1
2 Игорь 3

Тем самым сохранив их позиции в таблице и сдвинув подальше от предела типа unsigned double.

(Чтобы убрать возможное непонимание - говоря о позиции в таблице, имеется ввиду что позиции конкретных строк будут отображаться конечному пользователю в результате сортировки строк по полю position)

Тогда пересчет позиции не нужен, требуется только сортировать по условному числу

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

Но это опять несет некоторые неудобства.

Какие?

Каждый пользователь вводит некое число

Не годится. Пользователя не надо напрягать лишним вводом чисел. На стороне клиента, таблица выводиться с возможностью перетаскивания строк мышкой (drag&drop). Т.е. вс? должно быть на автомате.

Link to comment
Share on other sites

  • 0

Можно задать 3 переменные(или больше):

1ая- средняя граница, сначала позиция сравнивается с ней.

2ая- если позиция выше средней сравнить с верхней

3ья- если меньше нижней сравнивать с начала.

Вообще я такой способ придумал когда в галакт цивилизацию 3.5 года назад играл пиратскую, не известно сколько золота другая раса хотела получить за что-либо вот я так и перебирал:):):):)

Тут можно больше ключевых таких переменных сделать. Таким образом вся база данных скорее всего не будет перебираться и это в разы ускорит процесс. Будут проверено как минимум в 75%(верхния или нижняя половина, верхняя или нижняя четверть половину будут перебираться). Еще скажите плз это нормальное решение для того кто на программера учится?

Link to comment
Share on other sites

  • 0

2Vlad, с этим проблем нет, потому я это не оговариваю. На страницу выводиться по 500 записей. Пользователи могут выбирать с какой позиции записи выводить. Перетаскивание обычно находиться в диапазоне 50-100 записей, не больше, но менять их могут достаточно часто, каждую в сво?м диапазоне. Потому дробные части будут расти довольно быстро.

2IceBars, идея не совсем ясна. Можно разжевать?

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

Link to comment
Share on other sites

  • 0

Я так понимаю что нужно отсортировать все строки но их много и запросы к каждой нагружают сервер.

Чтобы не проверять каждую строку в мискл, можно создать ключевые позиции, по которым вначале будет определяться какие строки проверяются дальше. Допустим пользователь на 8593 месте из 10000. При использовании метода пузырька будет проверяться 8593 строки. Если создать ключевую точку на 5000, провериться она и т.к. 8593>5000 поиск во 2-ой половине. Затем ключевая точка 7500, то же самое. Затем 8625, и т.к. 8593<8625 будут сверяться строки с 7500 по 8625 а не с 1-ой. На (7500;8625) можно также задать ключевые точки.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. See more about our Guidelines and Privacy Policy