我有一个表,它在Stack1,Stack2,Stack3,Stack4,Stack5和Stack6列中存储代码。如果用户删除任何这些堆栈中的一个代码,我必须自动包装剩余的代码,以便可以将间隙移动到最后一个。
对于Eg: - 在上面的截图中,用户已经删除了Stack2中的代码,现在我希望stack3中的代码进入Stack2,Stack4中的代码进入Stack3。以下是预期的产出:
请提出解决方案。
答案 0 :(得分: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
我正在使用几个CTEs来取消堆叠并对堆栈进行排序,然后使用相关子查询更新每个堆栈。您可以在整个表上运行它,或者提供适当的where子句以获得更好的性能。
这里有几个假设:
ltrim(rtrim(coalesce(stack1, ''))) != ''
csCode, lane, row
生成一个候选键(唯一且没有一个为null)。如果csCode
本身是主键,那么在任何此查询中都不需要lane
或row
。答案 1 :(得分:-1)
Case
语句和Coalesce
的某些组合可以帮助您实现目标。如果没有所有边缘案例变体,提供精确的代码是很困难的,但 psuedo示例是您的可能的样子:
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
表并在select语句中使用ROW_NUMBER() OVER (Partition by codeParentID)
。
答案 2 :(得分:-1)
你必须在更新后编写一个触发器,如果堆栈列为空则将递归检查,如果是这种情况,则开始用stack [n]更新stack [n-1],很好问题你问。 / p>
此致
Ashutosh Arya