Как хранить заказы?

У меня есть приложение, в котором есть задачи, и вы можете их переупорядочить. Теперь я искал, как лучше их хранить. Должен ли я иметь colomn для номера порядка и пересчитывать все из них каждый раз, когда я его меняю? Пожалуйста, скажите мне версию, которая не требует, чтобы я обновлял все номера заказов, поскольку это очень трудоемко (с точки зрения исполнения).

Это особенно плохо, если я должен положить тот, который находится на самой вершине порядка, а затем перетащить его вниз.

  • Имя (порядковый номер)

-

  • 1 Пример (1)
  • 2 Пример (2)
  • 3 Пример (3)
  • 4 Пример (4)
  • 5 Пример (5)

-

  • 2 Пример (1) *
  • 3 Пример (2) *
  • 4 Пример (3) *
  • 5 Пример (4) *
  • 1 Пример (5) *

* необходимо изменить в базе данных

также некоторые задачи могут быть удалены из-за их выполнения

Ответ 1

Вы можете хранить заказы как литералы и использовать лексическую сортировку:

1. A
2. Z

Добавьте задачу:

1. A
3. L
2. Z

Добавить:

1. A
4. B
3. L
2. Z

Переместить 2 между 1 и 4:

1. A
2. AL
4. B
3. L

и др.

Вы обновляете только одну запись за раз: просто возьмите среднее письмо между первыми, которые отличаются: если вы помещаете между A и C, вы берете B, если вы помещаете между ALGJ и ALILFG, вы берете ALH.

Буква рядом с существующими счетчиками как существующими, объединенными с рядом с Z. I. e. если вам нужно поставить между ABHDFG и ACSD F, вы считаете его как между ABH и AB(Z+), и напишите AB(letter 35/2), то есть ABP.

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

Update:

Вы также можете сохранить свои данные в виде связанного списка.

См. статью в своем блоге о том, как это сделать в MySQL:

В двух словах:

/* This just returns all records in no particular order */

SELECT  *
FROM    t_list

id      parent
------- --------
1       0
2       3
3       4
4       1

/* This returns all records in intended order */

SELECT  @r AS _current,
        @r := (
        SELECT  id
        FROM    t_list
        WHERE   parent = _current
        )
FROM    (
        SELECT  @r := 0
        ) vars,
        t_list

_current id
-------  --------
0        1
1        4
4        3
3        2

При перемещении элементов вам необходимо обновить не более 4 строк.

Это, по-видимому, самый эффективный способ сохранить упорядоченный список, который часто обновляется.

Ответ 2

Обычно я добавляю столбец int или smallint с именем "Ordinal" или "PositionOrdinal", как вы предлагаете, и с точным предупреждением вы указываете — необходимость обновления потенциально значимого количества записей при каждом повторном заказе одной записи.

Преимущество заключается в том, что с учетом ключа для конкретной задачи и новой позиции для этой задачи код для перемещения элемента - это всего два оператора:

UPDATE `Tasks` SET Ordinal= Ordinal+1 WHERE Ordinal>[email protected]
UPDATE `Tasks` SET Ordinal= @NewPosition WHERE TaskID= @TaskID

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

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

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

Ответ 3

Из ваших ответов я придумал смесь, которая выглядит следующим образом:

Скажем, что у нас есть:

  • 1 Пример (1)
  • 2 Пример (2)
  • 3 Пример (3)
  • 4 Пример (4)
  • 5 Пример (5)

Теперь, если я отсортирую что-то между 4 и 5, это будет выглядеть так:

  • 2 Пример (2)
  • 3 Пример (3)
  • 4 Пример (4)
  • 1 Пример (4.5)
  • 5 Пример (5)

теперь снова что-то между 1 и 5

  • 3 Пример (3)
  • 4 Пример (4)
  • 1 Пример (4.5)
  • 2 Пример (4.75)
  • 5 Пример (5)

он всегда будет принимать половину разницы между цифрами

Я надеюсь, что это работает, пожалуйста, исправьте меня;)

Ответ 4

Мы делаем это с столбцом Sequence в базе данных.

Мы используем разреженную нумерацию (например, 10, 20, 30,...), поэтому мы можем "вставить" одну из существующих значений. Если соседние строки имеют последовательные числа, мы перенумеруем минимальное количество строк, которые мы можем.

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

Ответ 5

Это непростая задача. Если у вас есть небольшое количество сортируемых элементов, я бы просто reset все они в их новом порядке.

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

Вы можете делегировать эту работу на стороне клиента. Попросите клиента сохранить порядок старого порядка и порядок сортировки и определить, какая строка [порядок сортировки] должна быть обновлена, - затем передает эти кортежи в интерфейс PHP-mySQL.

Вы можете улучшить этот метод следующим образом (не требует поплавков):

  • Если все отсортированные элементы в списке инициализируются порядком сортировки в соответствии с их положением в списке, задайте порядок сортировки каждого элемента примерно как row [sort-order] = row [sort- порядок * K], где K - некоторое число > среднее число раз, когда вы ожидаете, что список будет переупорядочен. O (N), N = количество элементов, но увеличивает пропускную способность по крайней мере на N * K с по меньшей мере K открытыми слотами между каждой выходящей парой элементов.

  • Затем, если вы хотите вставить элемент между двумя другими, это так же просто, как изменить его порядок сортировки как один, который является > нижним элементом и < верхний. Если между элементами нет "комнаты", вы можете просто повторно применить алгоритм "распространения" (1), представленный в предыдущем абзаце. Чем больше K, тем реже будет применяться.

Алгоритм K будет выборочно применяться в PHP script, в то время как выбор нового порядка сортировки будет выполняться клиентом (возможно, Javascript).

Ответ 6

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

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