在序列中查找缺失值

时间:2012-02-17 12:24:39

标签: sql-server-2005

表1如下:

Col1
1
2
3
4
6
7
8
9
10
13
14

如上所示,col1具有值序列,但由于某种原因,用户未插入5,11等等。如何找出序列中的缺失值。这里的序列是1到14,缺失值是5,11。请帮帮我。

6 个答案:

答案 0 :(得分:4)

正如在其他答案中所说,最好的选择是使用真实序列表进行连接。您可以使用递归CTE创建一个:

DECLARE @MaxNumber INT
SELECT @MaxNumber = MAX(Col1) FROM YourTable;

WITH CTE AS
(
    SELECT 1 Col1
    UNION ALL
    SELECT Col1+1
    FROM CTE 
    WHERE Col1+1 <= @MaxNumber
)
SELECT A.Col1
FROM CTE A
LEFT JOIN YourTable B
ON A.Col1 = B.Col1
WHERE B.Col1 IS NULL
OPTION(MAXRECURSION 0)

答案 1 :(得分:3)

这适用于数字0 - 2000,对于大数字,您只需要交叉加入原始结果集。

with temp as (
  select distinct number
from master..spt_Values
where number between 0 and 2000
)

select * from
temp t
left join your_table y on y.col1 = t.number
where y.col1 is null 

或者使用交叉连接

这将对数十亿显然较慢的

起作用
    WITH
      L0   AS(SELECT 1 AS c UNION ALL SELECT 1),
      L1   AS(SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B),
      L2   AS(SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B),
      L3   AS(SELECT 1 AS c FROM L2 AS A CROSS JOIN L2 AS B),
      L4   AS(SELECT 1 AS c FROM L3 AS A CROSS JOIN L3 AS B),
      L5   AS(SELECT 1 AS c FROM L4 AS A CROSS JOIN L4 AS B),
      Nums AS(SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS n FROM L5)

  select * from
    l5 t
    left join your_table y on y.col1 = t.n
    where y.col1 is null 

答案 2 :(得分:0)

这似乎是

的重复

SQL query to find Missing sequence numbers

有一些建议可行:

SELECT      l.id + 1 as start
FROM        Table1 as l
LEFT JOIN   Table1 as r on l.id + 1 = r.id
WHERE       r.id IS NULL

否则,您可以使用序列表在表上保持连接。从上面的问题,您可以查看http://www.projectdmx.com/tsql/tblnumbers.aspx以获得有关如何生成合适的序列表的一些想法,并且连接将类似于

SELECT      #sequence.value
FROM        #sequence
LEFT JOIN   Table1 ON #sequence.value = Table1.value
WHERE       Table1.value IS NULL

答案 3 :(得分:0)

所有递归CTE建议的

侧注。递归CTE增加了与行数成线性关系的时间。使用计数表或交叉连接要好得多......

这样可行:

-- data table
CREATE TABLE #data (
    value INT
)

INSERT #data VALUES (1)
INSERT #data VALUES (2)
INSERT #data VALUES (3)
INSERT #data VALUES (4)
INSERT #data VALUES (6)
INSERT #data VALUES (7)
INSERT #data VALUES (8)
INSERT #data VALUES (9)
INSERT #data VALUES (10)
INSERT #data VALUES (13)
INSERT #data VALUES (14)

-- normally i have a tally table already for stuff like this but I'll
-- create one temporary here.
CREATE TABLE #tmp_tally (
    n INT
)

DECLARE @n INT
SET @n = 1
WHILE @n < 14
BEGIN
    INSERT #tmp_tally VALUES (@n)
    SET @n = @n + 1
END

SELECT
    T.n,
    CASE WHEN #data.value IS NULL THEN 'Missing' ELSE 'Not Missing' END
FROM
    #tmp_tally T
    LEFT JOIN #data ON
    T.n = #data.value
WHERE
    T.n <= (SELECT MAX(value) FROM #data) -- max of what you want to check against which is 14 in your example

DROP TABLE #data
DROP TABLE #tmp_tally

答案 4 :(得分:0)

试试这个:

declare @min int
declare @max int

select @min = min(field_ID), @max = max(field_ID) from [Table]

create table #tmp (Field_No int)
while @min <= @max
begin
   if not exists (select * from [Table] where field_ID = @min)
      insert into #tmp (seq_field) values (@min)
   set @min = @min + 1
end
select * from #tmp
drop table #tmp

使用上述脚本,您将在&#34; ID &#34;来自#tmp table的列。

希望这会对你有所帮助!!

答案 5 :(得分:-1)

我会在同一个表中执行子查询,以查看当前数字1是否存在另一个数字,如果没有,则表示已跳过一个数字。你也可以做+1。

选择     nt.numb,     案件         (从表中选择COUNT(*),其中numb = nt.numb-1)= 0然后'跳过'ELSE'没有被跳过' 从     numbertable nt