2010-11-24 50 views
0

在我的Products表中,我有一个名为'order'的列,其中包含用户在CMS中通过下拉框设置的整数1,2,3等。SQL Server:更改DB中的订单列

我希望能够通过相应地传递旧订单,新订单和产品ID来重新排序数据库中的所有行,当用户更改某个产品的订单时。

如:

Chair - order 1 
Pillow - order 2 
Bed - order 3 
Couch - order 4 

如果采用改变沙发是2阶,我需要根据这种变化重置所有其他产品。

优化不是一个巨大的问题,因为不会有很多表中的项目。

这个任务最有效的逻辑是什么?

感谢

+0

你的逻辑似乎并不完整。当用户更改为2时,适用于重置所有其他产品的逻辑是什么?重置标准? – InSane 2010-11-24 08:05:03

+1

你写*什么是最有效的逻辑* - 但也*优化不是一个巨大的关注*。那么,在这种情况下,*高效*意味着什么? – 2010-11-24 08:08:01

回答

1

order列并不需要包含连续整数 - 可以有差距。唯一重要的是他们的相对顺序。您可以从100,200,300 ...开始,而不是1,2,3,...使得更容易调整相对顺序,而不必仅仅因为要移动一个项目而更新数据库中的所有项目。

 
100 foo ---  200 bar 
200 bar \  300 baz 
300 baz  ---> 350 foo 
400 qux   400 qux 

偶尔您会发现在插入点处没有空隙。然后你可以重新编号整个表格。

0

如何像这样(伪代码)

UPDATE Table 
SET  Order = Order + 1 
WHERe Order >= NewOrderForCouch 
AND  Order < CurrentOrderForCouch; 
UPDATE Table 
SET  Order = NewOrderForCouch 
WHERe ID = CouchID; 
0

要做到这一点,你的表需要有一个唯一的标识符,要能够

Couch 2 

区分
Pillow 2 

创建你的订单表像这样

CREATE TABLE [dbo].[Orders](
    [ID] [int] NOT NULL, 
    [Item] [varchar](50) NOT NULL, 
    [Number] [int] NOT NULL, 
CONSTRAINT [PK_Orders] PRIMARY KEY CLUSTERED 
(
    [ID] ASC 
) ON [PRIMARY] 
) ON [PRIMARY] 

填充一次,你有这样的(注意我是如何把随机的唯一idenitifiers的唯一密钥ID):

ID  Item Number 
593 Chair 1 
207 Pillow 2 
681 Bed  3 
117 Couch 4 

你改变沙发的数量为2:

ID  Item Number 
593 Chair 1 
207 Pillow 2 
681 Bed  3 
117 Couch 2 

我们可以使用ID来区分沙发和枕头,两者都有号码2。该ROW_NUMBER()函数为我们提供了所需的编号:

SELECT 
    id, Item, number, ROW_NUMBER() OVER(ORDER BY number) 
FROM 
    Orders 

593 Chair 1 1 
117 Couch 2 2 
207 Pillow 2 3 
681 Bed  3 4 

然后只需用这些新的数字更新,使用的问题WITH子句:

WITH NewOrders(newnum, id) AS (
    SELECT 
     ROW_NUMBER() OVER(ORDER BY number), id 
    FROM 
     Orders 
) 
UPDATE 
    Orders 
SET 
    number = (
     SELECT 
      newnum 
     FROM 
      NewOrders 
     WHERE 
      neworders.id = orders.id  
    ) 

结果:

ID Item Number 
593 Chair 1 
117 Couch 2 
207 Pillow 3 
681 Bed  4 
1
CREATE PROCEDURE ChangeProductOrder(@productID int, @order int) 
AS 

DECLARE @oldOrder int 
SET @oldOrder = (SELECT [Order] FROM dbo.Products WHERE productid = @productID) 

UPDATE p 
SET [order] = CASE WHEN ProductID = @productID 
       THEN @order 
       ELSE [Order] - SIGN(@order - @oldOrder) 
       END 
FROM dbo.Products p 
WHERE ([Order] BETWEEN @oldOrder AND @order 
OR [Order] BETWEEN @order AND @oldOrder)