如何在`delete from ... into`查询中增加二级序列号?

时间:2017-08-03 18:28:26

标签: sql sql-server tsql

假设我是一个正在萌芽的宠物小精灵卡片收集器,我使用SQL数据库来跟踪我的卡片。我为Pokemon的每个种类指定了一个数字id。我想跟踪我收集的每种订单,因此我还为每张卡分配了一个序列号seqno。我把卡片放在架子上。

create table shelf (
    kind_id int not null,
    seqno int not null
)

insert into shelf values (0, 1), 
                         (0, 2),
                         (0, 3),
                         (1, 1),
                         (1, 2)

我只捕获了两种口袋妖怪:第一种中的三种和第二种中的两种。

当我去收集更多卡片时,我把它们丢进一个袋子里。

create table bag (
    kind_id int not null,
)

insert into bag values (0),
                       (0),
                       (1),
                       (2)  -- woot, caught a new one

将所有卡片从包裹移到货架上很容易......

delete from bag
output deleted.kind_id, -1
into shelf (kind_id, seqno)
select * from bag 

...然后使用-1提醒我设置序列号,但我已经厌倦了手动设置。

我也是一个非常类型的A编码器,我不想写第二个查询来更新序列号。我希望这一切都发生在"从包到货架的过程中#34;查询。

我知道,这些限制听起来很奇怪。我试图提炼出一个更复杂的问题,所以希望故事有所帮助。

2 个答案:

答案 0 :(得分:2)

将您的删除更改为插入然后删除。使用子查询从架子中找到MAX(seqnum)(与正确的id相关)并在插入期间递增它。将子查询包装在ISNULL('',1)中以便为新卡启动seqnum为1,(或在seqnum列上使用默认值约束):

SELECT b.kind_id, 
       ISNULL(seqno + ROW_NUMBER() OVER (PARTITION BY b.kind_id ORDER BY b.kind_id),1)
FROM bag b
LEFT JOIN (SELECT MAX(seqno) seqno, kind_id
           FROM shelf
           GROUP BY kind_id) s on s.kind_id = b.kind_id

然后只是DELETE FROM bag

答案 1 :(得分:0)

windows功能

select id 
     , row_number over (partition by id, order by id) as autoSeqno 
from shelf  

或者只使用行李包作为基准表而不是删除它