Подтвердить что ты не робот

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

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

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

Id    Order
5     3
8     1
26    2
32    5
120   4

Теперь, что я могу сделать, чтобы изменить порядок записи с ID=26 на 3?

Я создал процедуру, которая проверяет, есть ли запись в целевом порядке (3) и обновляет порядок строки (ID = 26), если нет. Если есть запись в целевом порядке, процедура выполняет сама посылка этого идентификатора строки с помощью target order + 1 в качестве параметров.

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

Id    Order
5     4
8     1
26    3
32    6
120   5

Итак, что мог бы сделать более умный человек?

  • Я использую SQL Server 2008 R2.

Edit:

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

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

4b9b3361

Ответ 1

Update product set order = order+1 where order >= @value changed

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

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

Альтернативное решение с учетом желания без пробелов:

Представьте процедуру для: UpdateSortOrder с параметрами @NewOrderVal, @IDToChange, @OriginalOrderVal

Двухэтапный процесс, зависящий, если новый/старый порядок перемещается вверх или вниз по сортировке.

If @NewOrderVal < @OriginalOrderVal --Moving down chain 

--Create space for the movement; no point in changing the original 
    Update product set order = order+1 
    where order BETWEEN @NewOrderVal and @OriginalOrderVal-1;

end if

If @NewOrderVal > @OriginalOrderVal --Moving up chain

--Create space  for the momvement; no point in changing the original  
  Update product set order = order-1 
  where order between @OriginalOrderVal+1 and @NewOrderVal
end if

--Finally update the one we moved to correct value

    update product set order = @newOrderVal where [email protected];

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

Ответ 2

Используйте старый трюк, который использует программы BASIC (среди других мест): переместите числа в столбце порядка на 10 или другое удобное приращение. Затем вы можете вставить одну строку (на самом деле, до 9 строк, если повезет) между двумя существующими номерами (это 10 друг от друга). Или вы можете перемещать строки с 370 по 565, не меняя ни одного из строк с 570 вверх.

Ответ 3

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

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

Это означает, что ваш SQL будет выглядеть примерно так:

ORDER BY 'weight', 'itemName'

надеюсь, что это поможет.

Ответ 4

В настоящее время я разрабатываю базу данных с древовидной структурой, которую нужно заказать. Я использую метод типа link-list, который будет заказываться на клиенте (а не в базе данных). Заказ можно также выполнить в базе данных с помощью рекурсивного запроса, но это не обязательно для этого проекта.

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

https://docs.google.com/document/d/14WuVyGk6ffYyrTzuypY38aIXZIs8H-HbA81st-syFFI/edit?usp=sharing

Ответ 5

Вот альтернативный подход, использующий общее табличное выражение (CTE).

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

/* For example, move Product with id = 26 into position 3 */
DECLARE @id int = 26
DECLARE @sortOrder int = 3


;WITH Sorted AS (
    SELECT  Id,
            ROW_NUMBER() OVER (ORDER BY SortOrder) AS RowNumber
    FROM    Product
    WHERE   Id <> @id
)

UPDATE  p
SET     p.SortOrder = 
        (CASE 
            WHEN p.Id = @id THEN @sortOrder
            WHEN s.RowNumber >= @sortOrder THEN s.RowNumber + 1
            ELSE s.RowNumber
        END)
FROM    Product p
        LEFT JOIN Sorted s ON p.Id = s.Id 

Ответ 6

Это очень просто. У вас должна быть "дыра в мощности".

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

  1. pk = 32 бита int

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

Вставка /UpdateL

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

  2. Если вы вставляете в начало таблицы, вы должны установить order = round("order of first record" / 2)

  3. Если вы вставляете в конец таблицы, вы должны установить order = round("max_bigint - order of last record" / 2)

  4. Если вы вставляете в середину, вы должны установить order = round("order of record before - order of record after" / 2)

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

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

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

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