SQL Server获取最多N个非整数表列的整数

时间:2014-04-30 19:32:01

标签: sql sql-server tsql

我有一个包含规范化的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处被切断,我有数千次修订。

2 个答案:

答案 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);