我有一个表,它在 Stack1、Stack2、Stack3、Stack4、Stack5 和 Stack6 列中存储代码。如果用户删除这些堆栈中的任何一个代码,我必须自动堆叠剩余的代码,以便可以将间隙移到最后一个。
例如:- 在上面的屏幕截图中,用户删除了 Stack2 中的代码,现在我希望 stack3 中的代码进入 Stack2,而 Stack4 中的代码进入 Stack3。以下是预期的输出:
请提出解决方案。
我有一个表,它在 Stack1、Stack2、Stack3、Stack4、Stack5 和 Stack6 列中存储代码。如果用户删除这些堆栈中的任何一个代码,我必须自动堆叠剩余的代码,以便可以将间隙移到最后一个。
例如:- 在上面的屏幕截图中,用户删除了 Stack2 中的代码,现在我希望 stack3 中的代码进入 Stack2,而 Stack4 中的代码进入 Stack3。以下是预期的输出:
请提出解决方案。
虽然标准化您当前的模式会很好,但这是更新表的一种可能性:
;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
是主键本身,那么您将不需要lane
或row
在任何此查询中。您必须编写一个触发器,更新后将递归检查堆栈列是否为空,如果是这种情况,则开始使用堆栈 [n] 更新堆栈 [n-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 。