SQL 批量重新排序行

发布于 2024-08-03 23:36:08 字数 301 浏览 2 评论 0原文

我有一个包含记录列表的表和一个名为“顺序”的列。我有一个 AJAX 脚本来向上或向下拖放表行,我想用它来执行查询,并在拖动行时对行进行重新排序。

在 PHP 中,我执行查询来获取记录的当前顺序。例如 1, 2, 3 ,4 AJAX 函数在拖/放完成后传递新顺序,例如 3、1、2、4

是否有一种简单的方法可以根据新值一次性对记录重新排序?我能看到的唯一其他选择是循环更新语句,例如 SET order = 1 where order = 3

但这肯定会导致 2 条记录具有相同的值吗?

抱歉,我知道这个描述可能有点令人困惑。

I have a table with a list of records, and a column called order. I have an AJAX script to drag and drop the table rows up or down which I want to use to perform a query, reordering the rows as they have been dragged.

In the PHP, I perform a query to get the current order of the records. eg 1, 2, 3 ,4
The AJAX function passes the new order after the drag/drop is complete, eg 3, 1, 2, 4

Is there a simple way to re-order the records in one go, based on the new values? The only other alternative I can see is looping through UPDATE statements eg SET order = 1 where order = 3

But surely this would result in 2 records having the same value?

Apologies, I know this description may be slightly confusing.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

早茶月光 2024-08-10 23:36:08

订单不应该是你的主键;使用 where 子句中的主键进行更新。

如果您确实愿意,可以使用相当长的 CASE 语句在一个查询中完成所有操作。示例:(

UPDATE foo
  SET order = CASE order
    WHEN 1 THEN 2
    WHEN 2 THEN 3
    WHEN 3 THEN 4
    WHEN 4 THEN 5
  END
WHERE order IN (1,2,3,4)

请记住,SQL 语句的行为就好像它们同时更改所有值,因此不会执行将 1 更改为 2,然后更改为 3 等操作。)

Order should not be your primary key; do the updates by using the primary key in the where clause.

You can do it all in one query using a fairly long CASE statement, if you really want to. Example:

UPDATE foo
  SET order = CASE order
    WHEN 1 THEN 2
    WHEN 2 THEN 3
    WHEN 3 THEN 4
    WHEN 4 THEN 5
  END
WHERE order IN (1,2,3,4)

(Remember that SQL statements behave as if they change all values simultaneously, so that will not do something like change 1 to 2, then to 3, etc.)

万水千山粽是情ミ 2024-08-10 23:36:08

如果您知道新的行位置,您可以执行以下操作:

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

If you know the new row position you can do this:

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
望她远 2024-08-10 23:36:08

您确实想回去看看 ajax 函数的结果。看看是否可以获得重新排序的元素列表,而不仅仅是新的列表顺序。

您可以编写一个函数(在 C#/VB 中)来在给定之前和之后列表的代码中确定这一点。一旦发生增量更改,您就可以针对每次重新订购发出一个更新命令来发出更新事务。

如果您只想使用新订单。尝试添加一个名为 neworder 的新列并更新它。然后在循环完成后批量更新 currentcolumn=newcolumn 。

You really want to go back and look at the ajax function results. See if you can get a list of reordered elements instead of just the new list order.

You could write a function (in C#/VB) to determine this for you in code given the before and after lists. Once you have the delta changes, you could issue an update transaction with one update command per reorder.

If you want to work with just the new order. Try adding a new column called neworder and update this. Then bulk update currentcolumn=newcolumn once done looping.

傾城如夢未必闌珊 2024-08-10 23:36:08

你可以做类似的事情

BEGIN
UPDATE Table SET order = order + 1 WHERE order >= new_pos
UPDATE Table SET order = new_pos WHERE order = old_pos
UPDATE Table SET order = order - 1 WHERE order < old_pos AND order > new_pos
COMMIT;

(未经测试,这只是一个指针)

You could do something like

BEGIN
UPDATE Table SET order = order + 1 WHERE order >= new_pos
UPDATE Table SET order = new_pos WHERE order = old_pos
UPDATE Table SET order = order - 1 WHERE order < old_pos AND order > new_pos
COMMIT;

(UNTESTED, THIS IS JUST A POINTER)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文