2012-07-22 65 views
2

T-SQL查询查找第一丢失的序列串(前缀+无)SQL查询查找第一丢失的序列串(前缀+无)

序列可以有一个前缀+持续没有。

前序列将

ID 
------- 
AUTO_500 
AUTO_501 
AUTO_502 
AUTO_504 
AUTO_505 
AUTO_506 
AUTO_507 
AUTO_508 

因此丢失的序列上面AUTO_503或者如果没有丢失的序列,那么它必须返回一个序列。

另外开始否是指定的前。 500,在这种情况下,前缀可以为空,即,不将前缀唯一的数字视为序列。

+1

如果可能的话R_Cds,[规范化数据库] (http://phlonx.com/resources/nf3/) – Esailija 2012-07-22 08:12:45

+0

这是一个很好的去,但现在DB冻结不能做到这一点。 。只需要解压出这个只有...... – Garry 2012-07-22 08:16:24

回答

4

你可以LEFT JOIN上移(+1)值的ID号来查找顺序差距:

SELECT 
    MIN(a.offsetnum) AS first_missing_num 
FROM 
(
    SELECT 500 AS offsetnum 
    UNION 
    SELECT CAST(REPLACE(id, 'AUTO_', '') AS INT) + 1 
    FROM tbl 
) a 
LEFT JOIN 
    (SELECT CAST(REPLACE(id, 'AUTO_', '') AS INT) AS idnum FROM tbl) b ON a.offsetnum = b.idnum 
WHERE 
    a.offsetnum >= 500 AND b.idnum IS NULL 

SQLFiddle Demo

+0

'也开始不是指定的前。 500'...与我们的解决方案,如果ID应该从AUTO_500开始,但ID输入从501开始,它只显示下一个缺失的不是,即503不是500这就是为什么我们需要指定起始范围。 PLZ更新你的解决方案保持这个约束以及....感谢 – Garry 2012-07-22 10:14:20

+0

@加里,用新的SQLFiddle编辑解决方案。 – 2012-07-22 10:33:03

+0

完美的解决方案... :) – Garry 2012-07-22 11:06:18

3

使用递归CTE动态生成的序列身份证号码的最小和最大值可能有点复杂,但它似乎有效 -

LIVE ON FIDDLE

CREATE TABLE tbl (
    id VARCHAR(55) 
); 

INSERT INTO tbl VALUES 
('AUTO_500'), 
('AUTO_501'), 
('AUTO_502'), 
('AUTO_504'), 
('AUTO_505'), 
('AUTO_506'), 
('AUTO_507'), 
('AUTO_508'), 
('509'); 

;WITH 

    data_cte(id)AS 
    (SELECT [id] = CAST(REPLACE(id, 'AUTO_', '') AS INT) FROM tbl) 

    ,maxmin_cte(minId, maxId)AS 
    (SELECT [minId] = min(id),[maxId] = max(id) FROM data_cte) 

    ,recursive_cte(n) AS 
    (
    SELECT [minId] n from maxmin_cte 
    UNION ALL 
    SELECT (1 + n) n FROM recursive_cte WHERE n < (SELECT [maxId] from maxmin_cte) 
) 

SELECT x.n 
FROM 
    recursive_cte x 
    LEFT OUTER JOIN data_cte y ON 
     x.n = y.id 
WHERE y.id IS NULL 
1

检查此解决方案。在这里您只需添加标识列。

CREATE TABLE tbl (
     id VARCHAR(55), 
     idn int identity(0,1) 
    ); 

    INSERT INTO tbl VALUES 
    ('AUTO_500'), 
    ('AUTO_501'), 
    ('AUTO_502'), 
    ('AUTO_504'), 
    ('AUTO_505'), 
    ('AUTO_506'), 
    ('AUTO_507'), 
    ('AUTO_508'), 
    ('509'); 

    SELECT min(idn+500) FROM tbl where 'AUTO_'+cast((idn+500) as varchar)<>id 
1

试试这个:

with cte as(
select cast(REPLACE(id,'AUTO_','') as int)-500+1 [diff],ROW_NUMBER() 
over(order by cast(REPLACE(id,'AUTO_','') as int)) [rnk] from tbl) 
select top 1 'AUTO_'+cast(500+rnk as varchar(50)) [ID] from cte 
where [diff]=[rnk] 
order by rnk desc 

SQL FIddle Demo

0

有类似的情况,在这里我们有一个是这样R01005

;with Active_R_CD (R_CD) 
As 
(
Select Distinct Cast(Replace(R_CD,'R', ' ') as Int) 
from table 
where stat = 1) 

select Arc.R_CD + 1 as 'Gaps in R Code' 
from Active_R_CD as Arc 
    left outer join Active_R_CD as r on ARC.R_CD + 1 = R.R_CD 
where R.R_CD is null 
order by 1