0

我有一个表,它在 Stack1、Stack2、Stack3、Stack4、Stack5 和 Stack6 列中存储代码。如果用户删除这些堆栈中的任何一个代码,我必须自动堆叠剩余的代码,以便可以将间隙移到最后一个。

在此处输入图像描述

例如:- 在上面的屏幕截图中,用户删除了 Stack2 中的代码,现在我希望 stack3 中的代码进入 Stack2,而 Stack4 中的代码进入 Stack3。以下是预期的输出:

在此处输入图像描述

请提出解决方案。

4

3 回答 3

1

虽然标准化您当前的模式会很好,但这是更新表的一种可能性:

;with piv as (
    -- Unpivot the data for ordering
    select csCode, lane, [row], 1 as ordinal, stack1 as stack from MyTable
    union all select csCode, lane, [row], 2 as ordinal, stack2 as stack from MyTable
    union all select csCode, lane, [row], 3 as ordinal, stack3 as stack from MyTable
    union all select csCode, lane, [row], 4 as ordinal, stack4 as stack from MyTable
    union all select csCode, lane, [row], 5 as ordinal, stack5 as stack from MyTable
    union all select csCode, lane, [row], 6 as ordinal, stack6 as stack from MyTable
)
, sort as (
    -- Order the stacks
    select *
        , row_number() over (partition by csCode, lane, [row] order by case when stack = '' then 1 else 0 end, ordinal) as stackNumber
    from piv
)
update a
    set stack1 = (select stack from sort where csCode = a.csCode and lane = a.lane and [row] = a.[row] and stackNumber = 1)
    , stack2 = (select stack from sort where csCode = a.csCode and lane = a.lane and [row] = a.[row] and stackNumber = 2)
    , stack3 = (select stack from sort where csCode = a.csCode and lane = a.lane and [row] = a.[row] and stackNumber = 3)
    , stack4 = (select stack from sort where csCode = a.csCode and lane = a.lane and [row] = a.[row] and stackNumber = 4)
    , stack5 = (select stack from sort where csCode = a.csCode and lane = a.lane and [row] = a.[row] and stackNumber = 5)
    , stack6 = (select stack from sort where csCode = a.csCode and lane = a.lane and [row] = a.[row] and stackNumber = 6)
from MyTable a

我正在使用几个CTE对堆栈进行反透视和排序,然后使用相关的子查询更新每个堆栈。您可以在整个表上运行它,或提供适当的 where 子句以获得更好的性能。

这里有几个假设:

  • 您的“空白”数据是一个空字符串。如果您可能有空格和空值,请对其进行清理或使用类似的内容对其进行限定ltrim(rtrim(coalesce(stack1, ''))) != ''
  • csCode, lane, row生成一个候选键(唯一的并且没有一个是空的)。如果csCode是主键本身,那么您将不需要lanerow在任何此查询中。
于 2013-08-27T13:52:43.900 回答
-1

您必须编写一个触发器,更新后将递归检查堆栈列是否为空,如果是这种情况,则开始使用堆栈 [n] 更新堆栈 [n-1],你问的问题很好。

问候

阿舒托什·艾莉亚

于 2013-08-27T12:51:35.433 回答
-1

一些Case陈述的组合,Coalesce应该让你到达那里。如果没有所有极端情况的变化,很难提供精确的代码,但是您的要求可能看起来像一个伪示例:

UPDATE MyTable 
       Stack1 =  Coalesce (Stack1, Stack2, Stack3, Stack4, Stack5, Stack6),
       Stack2 =  Coalesce (Stack2, Stack3, Stack4, Stack5, Stack6)
       Stack3 =  Coalesce (Stack3, Stack4, Stack5, Stack6),
       Stack4 =  Coalesce (Stack4, Stack5, Stack6),
       Stack5 =  Coalesce (Stack5, Stack6),
       Stack6 =  Stack6
WHERE ID = @SomeIDValue

话虽如此,您的问题带有数据库设计问题的味道。从您分享的内容来看,我宁愿在子表中有堆栈。

CodeParent
  * codeParentID
  * csCode
  * line
  * row

CodeStackChild
  * codeStackChildId  (int identity)
  * codeParentID
  *  stackValue

使用上面的表格设置,您可以删除堆栈中间的一个值,然后继续移动,而无需移动值。要按顺序获取值,您只需查询CodeStackChild表并ROW_NUMBER() OVER (Partition by codeParentID)在您的选择语句中使用 a 。

于 2013-08-27T12:49:12.490 回答