Ведение порядка сортировки строк таблицы базы данных

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

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

Конечно, установка начальных номеров сортировки до 100 200 300 400 и т.д. оставляет некоторое пространство для перемещения, но в какой-то момент оно сломается.

Есть ли правильный способ сделать это, может быть, совсем другой подход?


Добавлено-1:

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

Добавлено-2:

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

Ответ 1

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

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

Ответ 2

Забудьте правильно - проблема, которую вы хотите избежать, не будет большой проблемой, а скорее всего несколько операторов UPDATE в зависимости от вашей RDBMS (Im предполагает Oracle и что вы перемещаете статью вверх по списку):

UPDATE Articles
SET sort_number = sort_number + 1
WHERE sort_number BETWEEN :new_sort_number and :current_sort_number - 1;

UPDATE Articles
SET sort_number = :new_sort_number
WHERE article_id = :article_id;

Самое большое предостережение в том, что функциональность SET не работает одинаково во всех РСУБД.

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

Альтернативой поддержанию столбца номера сортировки будет сохранение столбца родительского идентификатора. Это, возможно, более корректно, поскольку он сохраняет сериализацию ваших данных, но недостатком является то, что запрос данных не является довольно или эффективным (например, CONNECT BY в Oracle).

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

Ответ 3

Модель вашей таблицы после структуры данных связанного списка. Избавьтесь от столбца "sort", вместо этого столбец next_article_id, который указывает на следующую статью после него. Затем, когда вы хотите добавить новую статью в позицию 50, вам нужно только обновить статью № 49, чтобы указать на новую статью, а затем указать новую статью на одну статью # 49, на которую указывалось ранее.

Ответ 4

Это довольно просто. Вам нужен "столбец заказа".

Чтобы использовать этот метод, вам нужно иметь как минимум 2 столбца:

  1. id - 32 бита int
  2. orderValue - 64 бита bigint (bigint, а не двойной !!!)

Вставка/Обновление

  1. При вставке первой новой записи вы должны
    set orderValue = round(max_bigint / 2).

  2. Если вы вставляете строку, которая принадлежит в начале списка, вы должны
    set orderValue = round("orderValue of previously inserted record" / 2)

  3. Если вы вставляете строку, которая принадлежит концу списка, вы должны
    set orderValue = round("max_bigint + orderValue of final record" / 2)

  4. Если вы вставляете куда-либо еще, вы должны
    set orderValue = round("orderValue of record before + orderValue of record after" / 2)

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

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

Это очень просто и быстро!

Помните - не используйте двойные символы !!! Только целые числа - столбцу orderValue нужна очень высокая точность!

Ответ 5

Использование реального числа, по-видимому, является наиболее эффективным с точки зрения вычислений выбором. Вы можете переместить ряд между двумя другими, добавив половину расстояния между двумя строками. Чтобы переместить newrow между row1 и row2, вычислите newrow как newrow = row1 + (row2 - row1)/2.0. Однако из-за пределов с плавающей запятой эта серия (с использованием двойной точности) сходится в 53 итерациях. В худшем случае вы можете сделать только 53 вставки (больше, если вы не всегда вставляете между последним newrow и row2). Это похоже на идею оставить пробелы и заполнить их. Идея сделать обновление менее эффективна, но не прерывается после определенного количества вставок. Сохранение индексированного столбца, вероятно, поможет.

Ответ 6

Чтобы построить ответ Alkini (я бы ответил на это напрямую, но на данный момент мне не хватает очков/привилегий). Этот метод работает только в том случае, если новый порядок отображения меньше, чем новый. Если это наоборот, вам нужно сдвинуть статьи между ними в другом направлении.

if (new_sort_number == current_sort_number)

Do nothing

if (new_sort_number < current_sort_number)

UPDATE Articles
SET sort_number = sort_number + 1
WHERE sort_number BETWEEN :new_sort_number and :current_sort_number - 1;

if (new_sort_number > current_sort_number)

UPDATE Articles
SET sort_number = sort_number - 1
WHERE sort_number BETWEEN :current_sort_number + 1 and :new_sort_number;

Затем в любом случае обновите статью, которая была перенесена.

UPDATE Articles
SET sort_number = :new_sort_number
WHERE article_id = :article_id;

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

Ответ 7

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

Если старую статью следует разместить поверх списка, просто установите ее столбец сортировки в MAX (Сортировка) +1. Нет необходимости перенумеровать всю таблицу.

Обновить после комментариев:

Измените порядок сортировки на плавающую точку. Если порядок сортировки статьи перегруппирован между двумя другими статьями, новое значение Сортировка устанавливается на ((Сортировка предыдущей статьи) + (вид следующей статьи))/2. В противном случае установите "Сортировка" в MAX + 1.

Ответ 8

Проблема, которую я хочу избежать, - это статьи, пронумерованные 1,2,3,4,.., 100

Я бы посоветовал вам не пытаться, чтобы ваш ключ сортировки был вашим основным ключом или был уникальным. Если они не уникальны, вы можете иметь несколько элементов с одинаковым значением. Вероятно, вы захотите просто сделать свой ключ сортировки простой шкалой 1-10.

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

Ответ 9

Чтобы сделать это, мы устанавливаем строки для увеличения целых чисел, а затем используйте хранимую процедуру для перемещения элементов. Proc принимает два аргумента, текущий индекс элемента и новый индекс, на который вы хотите переместить его. Он устанавливает элементы обновления index = index + sign (@newidx - @oldidx), где индексируется между itemMax (@newidx, @oldidx) и itemMin (@newidx, @oldidx) для обновления элементов между ними, а затем обновление, которое изменяется фактический элемент к новому индексу. Это не настоящий код, просто из памяти. В нашей таблице у нас есть два столбца: id и индекс, так что, хотя в какой-то момент вы получаете два элемента в одном и том же индексе, мы можем различать их по идентификатору. Это можно обойти, выполнив обновление элемента, который нужно перенести, и, возможно, индекс -1, затем обновить остальную часть и, наконец, переместить новый элемент в -1 в новый индекс.

Ответ 10

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

т.е. каждую ночь в полночь вы создаете табличный вид своей основной таблицы, но создаете ее только с помощью статей за последние 2 или 3 дня, а затем поддерживаете сортировку/количество процентов строго на этой таблице. Если кто-то выбирает старую статью не в этой таблице (скажем, неделю назад), вы всегда можете вставить ее в текущее представление. Таким образом, вы можете получить эффект от возраста.

Все дело в том, чтобы поддерживать небольшие индексы в таблице, где вставки и обновления значений сортировки/процента должны оставаться относительно быстрыми. Перед созданием представления вам нужно будет заплатить только за сложные объединения, а затем вы можете сохранить его на месте, чтобы оптимизировать чрезмерные чтения. Какой максимум у вас было бы в представлении, пару сотен, пару тысяч? Удары пытаются сортировать сто тысяч каждый раз, когда кто-то делает запрос.

Ответ 11

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

Ответ 12

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