获取每个部分缺少的数字

时间:2014-11-26 19:03:35

标签: sql sql-server tsql

我希望从每个部分的列表中获取缺少的协议编号 我有我的清单

    ProtocolNumber  Section
--------------------------------
    14A1000014  |     A1
    14A1000015  |     A1
    14A1000018  |     A1
    14A1000019  |     A1
    14A2000014  |     A2
    14A2000015  |     A2
    14A2000019  |     A2

我试试这个

SELECT  lb1.ProtocolNumber, lb1.Section  FROM #tmp lb1 
        WHERE not exists ( SELECT * FROM #tmp lb2
                       WHERE lb2.ProtocolNumber = lb1.ProtocolNumber + 1  and lb2.Section = lb1.Section)

输出应该是这样的

   ProtocolNumber   Section
--------------------------------
    14A1000016  |     A1
    14A1000017  |     A1
    14A2000016  |     A2
    14A2000017  |     A2
    14A2000018  |     A2

3 个答案:

答案 0 :(得分:2)

假设您正在尝试生成该部分当前存在的最小和最大范围之间缺少协议编号的列表,我建议如下:

/*Sample Data*/
CREATE TABLE #tmp (ProtocolNumber VARCHAR(20), Section VARCHAR(2))
INSERT INTO #tmp (ProtocolNumber, Section) SELECT'14A1000014',      'A1' 
INSERT INTO #tmp (ProtocolNumber, Section) SELECT'14A1000015',      'A1'
INSERT INTO #tmp (ProtocolNumber, Section) SELECT'14A1000018',      'A1'
INSERT INTO #tmp (ProtocolNumber, Section) SELECT'14A1000019',      'A1'
INSERT INTO #tmp (ProtocolNumber, Section) SELECT'14A2000014',      'A2'
INSERT INTO #tmp (ProtocolNumber, Section) SELECT'14A2000015',      'A2'
INSERT INTO #tmp (ProtocolNumber, Section) SELECT'14A2000019',      'A2'

/*CTEs to generate numbers list: 1 through 1,000,000*/
;WITH 
    E1(N) AS (SELECT 1 FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) s(N)), 
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows 
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max 
    E5(N) AS (SELECT 1 FROM E4 a, E2 b), --1,000,000 rows max 
    cteTally(N) AS ( SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E5 ),
/*CTE to identify ranges of current numbers for each Section*/
    Ranges AS 
      (
        SELECT 
            Section, 
            MIN(CAST(SUBSTRING(ProtocolNumber, 5,6) AS INT)) MinNumber, 
            MAX(CAST(SUBSTRING(ProtocolNumber, 5,6) AS INT)) MaxNumber
        FROM 
            #tmp 
        GROUP BY Section 
      ),
/*CTE to generate full list of available protocols for each Section*/
    ProtocolList AS 
      (
        SELECT DISTINCT 
            Section,
            '14' + Section + RIGHT('00000' + CAST(N AS VARCHAR(6)),6) AS ProtocolNumber
        FROM Ranges 
         INNER JOIN 
        cteTally ON 
            cteTally.N >= Ranges.MinNumber AND 
            cteTally.N <= Ranges.MaxNumber

      )

/*Final SELECT - protocols in the master list that do not exist for those sections in the temp table*/

SELECT l.ProtocolNumber, l.Section
FROM 
    ProtocolList l
     LEFT JOIN 
    #tmp t ON 
        l.ProtocolNumber = t.ProtocolNumber
WHERE t.ProtocolNumber IS NULL 
ORDER BY 
    l.Section, 
    l.ProtocolNumber

DROP TABLE #tmp 

答案 1 :(得分:0)

是否必须是一行选择陈述?

如何编写存储过程或表值函数,使用游标遍历表并创建缺失记录,函数返回

实施还需要检查每个给定部分的最大协议编号,以便您只创建范围内的记录

答案 2 :(得分:0)

遗失议定书清单

 DECLARE @P INT=(SELECT  COUNT(DISTINCT SECTION) FROM PROTOCOL) --NUMBER OF SECTION
DECLARE @w varchar(10)='A1'   --HOLD TYPE OF SECTION
WHILE @P>0
BEGIN
DECLARE @q table(numx int)  --HOLD MAX TO MIN ProtocolNumber
declare @i table(num int)   --HOLD EXISTS 'ProtocolNumber'
INSERT INTO @i
select  convert(int,right( ProtocolNumber,2)) FROM protocol  WHERE Section=@w
DECLARE @x int=(select max(convert(int,right( ProtocolNumber,2))) FROM protocol WHERE Section=@w)
DECLARE @y int=(select min(convert(int,right( ProtocolNumber,2))) FROM protocol WHERE Section=@w)
 WHILE @y <= @x  
begin
INSERT INTO @q (numx)
VALUES(@y)
SET @y= @y + 1
END
SELECT ('14'+@w+'0000'+ convert(varchar(10),numx)) AS ProtocolNumber,@W AS Section
FROM  @Q
 where  numx NOT IN (select  * FROM @i)
  SET @P=@P-1
 SET @W='A2'
 DELETE FROM @Q
 DELETE  FROM @I
 END

enter image description here