Как разработать таблицу, которая может быть повторно упорядочена?

Если предыдущее (и логичный) ответы о '|' не подходят Вам, взглянули на телефон

http://metacpan.org/pod/Regex::PreSuf

описание модуля: создайте регулярные выражения из списков слов

8
задан Kev 23 October 2009 в 20:37
поделиться

7 ответов

The obvious answer to me is to use the last solution you mentioned but with decimals (floats).

So you start with, say: {0.1, 0.2, 0.3, 0.4, 0.5}. If you move the last item to between 0.2 and 0.3 it becomes 0.25. If you move it to the top it becomes 0.05. Each time you simply take the mid-point of the two numbers on either side. In other words, the average of the previous/next items.

Another similar solution is to use characters, then sort by strings alphabetically. Starting with {1, 2, 3, 4, 5}, if you move the 5 between 2 and 3 you'd use 25. If you do a string sort of the list you keep the right order: {1, 2, 25, 3, 4}.

The only problem I can think of with these methods is that eventually, you will hit the limit of floating point precision, i.e. trying to find a number between 0.0078125 and 0.0078124. A few ways to solve this:

  • Run a script every so often that runs through every item and reorders them to {0.1, 0.2, 0.3, ...}.
  • Don't use two decimal places when you can use one. Between 0.2 and 0.25 you could use 0.23 instead of the calculated 0.225.
  • Re-sequence locally, not globally. If you have {0.2, 0.3, 0.6} and want to insert after 0.2, you could set the second one to 0.4 and insert the new item at 0.3.
10
ответ дан 5 December 2019 в 11:25
поделиться

ID и Sequence / SortOrder являются отдельными и не должны зависеть друг от друга.

для функции перемещения вверх / вниз: Вы можете поменять местами значения Sequence / SortOrder

или

Для функции перетаскивания:

1) Установите новый Sequence / OrderNumber для выбранной записи.

2) Получите текущую последовательность выбранных записей, затем Обновить выбранную запись новым номером.

3) a) Если новый порядковый номер ниже текущего порядкового номера, увеличьте все порядковые номера для записей, у которых порядковый номер> = новый порядковый номер (исключая выбранный)

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

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

У меня есть реализовал это в одном операторе SQL, который имеет небольшой объем логики, не для пуристов, но работает хорошо.

Вот пример (OP: вы захотите изменить идентификаторы GUID на INT):

CREATE PROCEDURE [proc_UpdateCountryRowOrder]
    @ID UNIQUEIDENTIFIER,
    @NewPosition INT
AS

SET NOCOUNT ON

DECLARE @CurrentPosition INT
DECLARE @MaximumPosition INT

IF (@NewPosition < 1) SET @NewPosition = 1

SELECT @CurrentPosition = [Countries].[Order]
FROM [Countries]
WHERE [Countries].[ID] = @ID

SELECT @MaximumPosition = MAX([Countries].[Order])
FROM [Countries]

IF (@NewPosition > @MaximumPosition) SET @NewPosition = @MaximumPosition

IF (@NewPosition <> @CurrentPosition)
BEGIN
    IF (@NewPosition < @CurrentPosition)
    BEGIN
        BEGIN TRAN

        UPDATE [Countries]
        SET [Countries].[Order] = [Countries].[Order] + 1
        WHERE [Countries].[Order] >= @NewPosition
        AND [Countries].[Order] < @CurrentPosition

        UPDATE [Countries]
        SET [Countries].[Order] = @NewPosition
        WHERE ID = @ID

        COMMIT TRAN
    END
    ELSE
    BEGIN
        BEGIN TRAN

        UPDATE [Countries]
        SET [Countries].[Order] = [Countries].[Order] - 1
        WHERE [Countries].[Order] <= @NewPosition
        AND [Countries].[Order] > @CurrentPosition

        UPDATE [Countries]
        SET [Countries].[Order] = @NewPosition
        WHERE ID = @ID

        COMMIT TRAN
    END
END
GO
3
ответ дан 5 December 2019 в 11:25
поделиться

Как насчет связанных списков? : -)

CREATE TABLE item(
    id INT PRIMARY KEY,
    prev INT,
    next INT
);

WITH RECURSIVE sequence AS (
    SELECT item.id, item.prev, item.next FROM item
    WHERE item.prev IS NULL
  UNION
    SELECT item.id, item.prev, item.next FROM sequence
    INNER JOIN item ON sequence.next = item.id
)
SELECT * FROM sequence;

На самом деле у меня под рукой нет PostgreSQL, чтобы проверить, действительно ли это работает (а MySQL не поддерживает SQL-99 WITH RECURSIVE ), и я не рекомендую серьезно это тоже.

2
ответ дан 5 December 2019 в 11:25
поделиться

- Изменить: просто для других, читающих этот пост, я был отклонен из-за какой-то странной личной неприязни, а не из-за общей неточности в отношении этой темы, учтите это при чтении и проголосуйте как вы хотите! :)

- Старый:

Типичный способ сделать это - использовать ваш номер «Sequence» (я называю его «SortOrder»).

Это действительно довольно просто.

«Масштабируемость» не делает ' т войти в это; потому что у вас уже есть список всех узлов, над которыми вы работаете (перетаскивайте, как вы говорите), так что на самом деле вы просто меняете местами эти числа.

Тривиально.

-1
ответ дан 5 December 2019 в 11:25
поделиться

Я сделал это, вернув CSV-строку идентификаторов (ключей БД) в порядке, выбранном пользователем на сервер. У меня есть функция на моем db, которая преобразует строку csv в таблицу с двумя полями - идентификатором и последовательностью (которая на самом деле является int с идентификатором). Значения поля последовательности в этой временной таблице отражают порядок элементов в строке CSV. Затем я обновляю таблицу данных, добавляя новое значение поля последовательности, соответствующее идентификаторам.

Изменить: награды выглядели так вкусно, я подумал, что предоставлю некоторые подробности своего ответа. Вот код:

declare @id_array varchar(1000)
set @id_array = '47,32,176,12,482'

declare @id_list_table table ([id] int, [sequence] int)

insert @id_list_table ([id], [sequence])
  select [id], [sequence]
  from get_id_table_from_list (@id_array)

update date_table
  set [sequence] = id_list.[sequence]
  from date_table
    inner join @id_list_table as id_list
      on (id_list.[id] = date_table.[id])

Я установил @id_array как переменную для тестирования - обычно ваш пользовательский интерфейс получает значения id в их измененном порядке и передает их как параметр в сохраненную процедуру. Функция get_id_table_from_list анализирует строку csv в таблицу с двумя столбцами типа int: [id] и [sequence]. Столбец [последовательность] является идентификатором. Результаты работы этой функции с моими тестовыми данными выглядят следующим образом:

    id   seq
    47   1  
    32   2  
    176  3  
    12   4  
    482  5  

Вам понадобится функция, которая будет анализировать csv (я могу опубликовать свою, если вам интересно, и я видел, как другие писали здесь и там). Обратите внимание, что в моем коде предполагается, что вы используете sql-сервер - последовательность операций зависит от поля идентификатора, а запрос на обновление использует расширение T-SQL (предложение 'from') - если вы используете какой-либо другой db, вам потребуется внесите несколько простых изменений.

0
ответ дан 5 December 2019 в 11:25
поделиться

Это исправление проще, чем вы думаете. Одна временная таблица и один запрос на обновление - и готово.


CREATE TABLE #TempData
(
NewSequence bigint identity(1,1),
[Id] BigInt
)

INSERT INTO #TempData ([Id])
SELECT [Id] 
FROM TableNameGoesHere
ORDER BY Sequence

UPDATE TableNameGoesHere
SET Sequence = t2.NewSequence
FROM TableNameGoesHere t1
INNER JOIN #TempData t2
ON t1.[Id] = t2.[Id]

DROP TABLE #TempData
0
ответ дан 5 December 2019 в 11:25
поделиться

I answered a similar question here : Visually order large data sets

If you move many items then you have to loop and move each item and check for overflow also. But all in all, the basic logic is to have a sorting column with gaps that can be reinitialized periodically.

1
ответ дан 5 December 2019 в 11:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: