给出下表:
aID | bID | idx
1 | 1 | 0
2 | 2 | 0
2 | 3 | 1
3 | 1 | 0
4 | 2 | 0
4 | 3 | 1
4 | 4 | 2
是否仅使用DELETE和UPDATE语句而不使用CURSORS可以获得以下结果?
aID | bID | idx
1 | 1 | 0
2 | 2 | 0
2 | 3 | 1
4 | 4 | 0
每个aID必须具有唯一的bID列表。 idx列仅描述列表的顺序。
我想删除所有多个bID,仅保留具有最低aID的bID。然后根据需要更新其余行的idx。
谢谢。
答案 0 :(得分:3)
这似乎可以完成工作:
declare @t table (aID int, bID int, idx int)
insert into @t(aID,bID,idx) values
(1,1 ,0 ),
(2,2 ,0 ),
(2,3 ,1 ),
(3,1 ,0 ),
(4,2 ,0 ),
(4,3 ,1 ),
(4,4 ,2 )
delete
t1
from @t t1
where exists (select * from @t t2 where t2.bID = t1.bID and t2.aID < t1.aID)
;With Numbered as (
select *,ROW_NUMBER() OVER (PARTITION BY aID ORDER by bID) -1 as newIdx
from @t
)
update Numbered set idx = newIdx
select * from @t
一旦您用语言阐明了您的要求,查询的逻辑就会自然而然地产生。删除行,其中另一行具有相同的bID
和较低的aID
值。
然后idx
只是基于每个aID
的单独序列的行号。当然,这确实提出了一个问题,为什么我们可以在很容易计算 1 的情况下完全存储它们。
结果:
aID bID idx
----------- ----------- -----------
1 1 0
2 2 0
2 3 1
4 4 0
(请注意,我已经使用SQL Server对此进行了测试-您没有对问题应用任何产品特定的标签-表变量语法是非标准的,而delete ... from
有点可疑,但是其余的是标准SQL)
1 通常的经验法则是仅存储 base 数据,而不存储派生的数据。通过单独存储派生数据,可以为计算值与基础数据不同步提供机会。
第二个经验法则是,如果您必须存储派生数据,理想情况下,由数据库引擎而不是您自己负责维护数据。但是通常只有在计算成本过高且您严重偏向读者而不是作家的情况下。
答案 1 :(得分:0)
使用相关子查询
select t.* from your_table t
where aID = (select min(aID) from your_table t1
where t1.bID=t.bID
)