我有一个包含规范化的subversion日志的sql server数据库表。但是,缺少一些修订。如何获得所有缺失的修订?
我试过
SELECT Revision + 1
FROM SvnLog
WHERE Revision + 1 NOT IN (SELECT Revision FROM SvnLog)
但是在缺少范围的情况下,在第一次缺失修订之后会遗漏任何内容。例如,如果缺少100-110,则只能获得100。
我也试过
WITH revs(rev) AS (
SELECT 0
UNION ALL
SELECT revs.rev + 1
FROM revs
WHERE revs.rev <90000
)
SELECT rev
FROM revs
WHERE rev NOT IN (SELECT Revision from SVNLog)
但CTE中的递归在100处被切断,我有数千次修订。
答案 0 :(得分:2)
我发现使用数字中的间隙长度更容易接近这个问题,而不是单独列出每个问题。毕竟,对数万或数十万行进行递归可能不如你想要的那么高。
您没有指定正在使用的SQL Server版本。在SQL Server 2012中,使用lag()
可以轻松完成此操作。但这是一个更通用的版本:
select (revision + 1) as gapStart, (nextrevision) - 1 as gapEnd
from (select l.revision,
(select min(l2.revision)
from SVNLog l2
where l2.revision > l.revision
) as NextRevision
from SVNLog l
) l
where nextrevision <> revision + 1;
为了提高性能,您需要SVNLog(Revision)
上的索引。
这也忽略了初始差距和某些其他细节。然而,在填写之前,我不知道这种格式是否符合您的需求。
顺便说一下,如果你想知道是否有任何缺口,你可以这样做:
select (max(revision) - min(revision) + 1) - count(distinct revision)
from SVNLog l;
如果没有间隙,则返回0
。否则,就有差距。
答案 1 :(得分:0)
有OPTION
控制CTE
的递归部门。您可以使用MAXRECURSION 0
删除限制。
WITH revs(rev) AS (
SELECT 0
UNION ALL
SELECT revs.rev + 1
FROM revs
WHERE revs.rev <90000
)
SELECT rev
FROM revs
WHERE rev NOT IN (SELECT Revision from SVNLog)
OPTION (MAXRECURSION 0);