Reputation: 1453
I have a table of different versions of files. All the versions of a file should be marked deleted except for the last one.
file_key | path | version | is_deleted
----------+-------+---------+------------
1 | foo/1 | 1 | f <=== wrong
2 | foo/1 | 2 | f <=== wrong
3 | foo/1 | 3 | f
4 | bar/2 | 1 | t
5 | bar/2 | 2 | t
6 | bar/2 | 3 | f
I'm looking for a query to find those first two rows and mark them is_deleted
. I've stumbled around with some self-joins and only ended up with combinatorials, and a "with" CTE was starting to look infinitely recursive.
Is there a sql solution for this, or should I just write a cursor?
Upvotes: 1
Views: 54
Reputation: 69524
Test Data
DECLARE @t TABLE (file_key INT, [Path] VARCHAR(10),[Version] INT, is_deleted CHAR(1))
INSERT INTO @t
VALUES
(1,'foo/1',1,'f'), (2,'foo/1',2,'f'),(3,'foo/1',3,'f'),
(4,'bar/2',1,'t'),(5,'bar/2',2,'t'),(5,'bar/2',3,'f')
Query (For Sql-Server)
;WITH LatestVersions
AS
(
SELECT *, rn = RANK() OVER (PARTITION BY [Path] ORDER BY [Version] DESC)
FROM @t
)
UPDATE LatestVersions
SET is_deleted = 't'
FROM LatestVersions
WHERE rn > 1
Result Set
╔══════════╦═══════╦═════════╦════════════╗
║ file_key ║ Path ║ Version ║ is_deleted ║
╠══════════╬═══════╬═════════╬════════════╣
║ 1 ║ foo/1 ║ 1 ║ t ║
║ 2 ║ foo/1 ║ 2 ║ t ║
║ 3 ║ foo/1 ║ 3 ║ f ║
║ 4 ║ bar/2 ║ 1 ║ t ║
║ 5 ║ bar/2 ║ 2 ║ t ║
║ 5 ║ bar/2 ║ 3 ║ f ║
╚══════════╩═══════╩═════════╩════════════╝
Upvotes: 3