用于重新排序表2

时间:2016-02-05 20:10:30

标签: sql sql-server stored-procedures

我有2张桌[Pubs]和[作者]。 [Pubs}可以有很多[作者]和[作者]可以创作很多[Pubs]所以我创建了一个联结表[Pub_Authors]来处理多对多关系。

每位作者都会在酒吧中获得优先权,并且主要作者或出版经理会不时地为作者重新分配新的优先权。

TABLE STRUCTURE:
PA_ID INT
PUB_ID INT
AUTH_ID INT
PA_PRIORITY INT
OLD_PRI (I added this based on a possible solution found here)

问题: 当主要作者重新分配优先级时,我需要重新编号其余的作者'从那时起,该酒吧的优先事项。

PA_ID   PUB_ID  AUTH_ID PA_PRIORITY  O_PRI
1       11      10      1            1
2       11      20      2            2
3       11      30      3            3

上面的示例显示了包含3位作者的ONE pub的数据。 出版经理将AUTHOR 20的优先级从2更改为3。

应该发生什么:

PA_ID   PUB_ID  AUTH_ID PA_PRIORITY  O_PRI
1       11      10      1            1
2       11      20      3            2
3       11      30      2            3

这是我在另一个例子中找到的SP,但它并没有完全符合我的要求...它将所有优先级更改为" 3&#34 ;而不是重新排序。

ALTER  Proc update_Publication_Author_Priority_Order (@ID Int, @NewPosition Int = 1)
As

Declare @OldPosition Int,
    @Direction Int

Select  @OldPosition = PA_PRIORITY 
From    Pub_Authors
Where   PUB_ID = @ID

Set     @Direction =    Case 
                    When    @OldPosition < @NewPosition Then 0
                    When    @OldPosition > @NewPosition Then 1
                    Else    -1
                    End

Update  t
Set     oldPri = PA_PRIORITY ,
    PA_PRIORITY =  Case
                When    PUB_ID = @ID Then @NewPosition
                When    @Direction = 0 And 
                        PA_PRIORITY Between @OldPosition And @NewPosition Then PA_PRIORITY - 1
                When    @Direction = 1 And 
                        PA_PRIORITY Between @NewPosition And @OldPosition Then PA_PRIORITY + 1
                Else    PA_PRIORITY 
                End
From    Pub_Authors t

我确定有一个简单的解决方案,我忽略了......任何帮助都会受到赞赏。

谢谢, 鲍勃

好的......经过认真考虑,反复试验,这就是我提出的可能的解决方案。我现在的问题是CASE声明中的多个指令......

Update  t
Set     oldPri = PA_Priority,
    PA_Priority =  Case  -- add a counter and increment within the loop.
                When    PA_Priority < @NewPosition Then PA_Priority
                        @Counter + 1
                When    PA_Priority = @NewPosition Then @Counter
                        @Counter + 1
                When    PA_Priority > @NewPosition Then @Counter
                        @Counter + 1
                Else    PA_Priority
                                                         @Counter + 1
                End

来自Pub_Authors t 其中PUB_ID IN(选择publicationID                             来自Pub_Authors                             Pub_ID = @ID)

2 个答案:

答案 0 :(得分:1)

纠正你已经拥有的最简单的方法就是修复一些地方。

Select  @OldPosition = PA_PRIORITY 
From    Pub_Authors
Where   PUB_ID = @ID

应该是

Select  @OldPosition = PA_PRIORITY 
From    Pub_Authors
Where   PA_ID = @ID

然后您的更新WHERE需要更改以获取正确的pub_ids并且第一个CASE需要查看PA_ID

UPDATE  t
SET     oldPri = PA_PRIORITY,
        PA_PRIORITY = CASE WHEN PA_ID = @ID THEN @NewPosition
                           WHEN @Direction = 0
                                AND PA_PRIORITY BETWEEN @OldPosition AND @NewPosition THEN PA_PRIORITY - 1
                           WHEN @Direction = 1
                                AND PA_PRIORITY BETWEEN @NewPosition AND @OldPosition THEN PA_PRIORITY + 1
                           ELSE PA_PRIORITY
                      END
FROM    Pub_Authors t
WHERE   PUB_ID IN (SELECT   PUB_ID
                   FROM     Pub_Authors
                   WHERE    PA_ID = @ID)

您也可以使用ROW_NUMBER执行此操作。我已经对它进行了几次测试,似乎有效。

CREATE PROCEDURE update_Publication_Author_Priority_Order (
     @ID INT,
     @NewPosition INT = 1
    )
AS 
    BEGIN
        WITH cte AS
        (
            SELECT  *,
                    ROW_NUMBER() OVER (ORDER BY CASE WHEN PA_ID = @ID THEN @NewPosition ELSE [PA_PRIORITY] END, [PA_PRIORITY] DESC) Rn 
            FROM    Pub_Authors
            WHERE   PUB_ID IN (SELECT PUB_ID FROM Pub_Authors WHERE PA_ID = @ID)
        )      
        UPDATE cte SET [PA_PRIORITY] = Rn, [O_PRI] = [PA_PRIORITY];

    END
GO 

scipy.sparse

答案 1 :(得分:0)

所以基本上你的问题是如何在表中保留一个可更新的订单列。最简单的方法是将oreder保存在数字列而不是int列中,这样您就可以将任何记录设置到任何地方而不更新talbe中的任何其他行。假设您要将第四条记录移至第二位。您所要做的就是将它的数字更新为1.5。