2012-07-22 105 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