Поддержание порядка сортировки строк таблицы базы данных - PullRequest
10 голосов
/ 29 декабря 2008

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

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

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

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


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

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

Добавлен-2

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

Ответы [ 12 ]

10 голосов
/ 30 декабря 2008

Забудьте правильно - проблема, которую вы хотите избежать, не будет большой проблемой, а всего лишь парой операторов UPDATE в зависимости от вашей СУБД (я предполагаю, что 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).

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

8 голосов
/ 29 декабря 2008

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

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

5 голосов
/ 30 декабря 2008

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

4 голосов
/ 21 августа 2014

(простите за английский. Я учусь)

Очень просто. Вам нужна "кардинальная дыра"

структура, вам нужно иметь 2 столбца

1) pk = 32 бита, int

2) order = 64bit bigint (БОЛЬШОЙ, НЕ ДВОЙНОЙ !!!)

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

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

2) если вы вставляете в начало таблицы, вы должны установить order = round («порядок первой записи» / 2)

3) если вы вставляете в конец таблицы, вы должны установить order = round ("max_bigint - порядок последней записи" / 2)

4) если вы вставляете в середину, вы должны установить order = round («порядок записи до - порядок записи после» / 2)

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

в ситуации максимальности с нормализацией (с этой структурой) вы можете иметь «дыру в кардинальности» в 32 битах.

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

помните, НЕТ ДВОЙНОЙ !!! Только INT - порядок является значением точности!

1 голос
/ 19 февраля 2017

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

if (new_sort_number == current_sort_number)

Do nothing

if (new_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;

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

1 голос
/ 05 мая 2010

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

0 голосов
/ 30 декабря 2008

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

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

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

0 голосов
/ 30 декабря 2008

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

0 голосов
/ 29 декабря 2008

Я хочу избежать проблемы с статьи пронумерованы 1,2,3,4, .., 100

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

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

0 голосов
/ 29 декабря 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...