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

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

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

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

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


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

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

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

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

12 ответов

Решение

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

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

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

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

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

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

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

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

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

1) рк = 32 бита int

2) порядок = 64-битный бигинт (БОЛЬШОЙ, НЕ ДВОЙНОЙ!!!)

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

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

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

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

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

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

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

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

помните, нет двойного! Только INT - порядок является точным значением!

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

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

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

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

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

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

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

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

Если более старая статья должна быть размещена в верхней части списка, просто установите для ее столбца Сортировка значение МАКС. (Сортировка)+1. Не нужно перенумеровывать всю таблицу.

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

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

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

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

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

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

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

Другие вопросы по тегам