Reputation: 8382
Suppose I'm a budding Pokemon card collector, and I use a SQL database to keep track of my cards. I assign each kind of Pokemon a number, id
. I want to keep track of the order I collected each kind, so I also assign each card a sequence number seqno
. I display the cards on a shelf.
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)
I've only caught two kinds of Pokemon: three of the first kind and two of the second.
When I go collect more cards, I throw them in a bag.
create table bag (
kind_id int not null,
)
insert into bag values (0),
(0),
(1),
(2) -- woot, caught a new one
It's easy to move all my cards from the bag to the shelf...
delete from bag
output deleted.kind_id, -1
into shelf (kind_id, seqno)
select * from bag
...and then use -1
to remind me to set the sequence number, but I'm tired of setting it manually.
I'm also a very type-A coder, and I don't want to write a second query to update the sequence numbers. I want it all to happen within the "move from bag to shelf" query.
The constraints sound odd, I know. I'm trying to distill a more complex problem, so hopefully the story helps.
Upvotes: 1
Views: 190
Reputation: 10277
Change your delete-into to an insert then delete. Use a subquery to find the MAX(seqnum)
from shelf (correlated to the correct id) and increment it during the insert. Wrap the subquery in ISNULL('',1)
to start the seqnum at 1 for new cards, (or use a default value constraint on the seqnum column):
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
Then just DELETE FROM bag
Upvotes: 2
Reputation: 45096
windows function
select id
, row_number over (partition by id, order by id) as autoSeqno
from shelf
or just use bag for the base table and don't delete it
Upvotes: 0