Sql 获取每个部分缺少的编号
我想从每个部分的列表中获取缺少的协议编号 我有我的名单Sql 获取每个部分缺少的编号,sql,sql-server,tsql,Sql,Sql Server,Tsql,我想从每个部分的列表中获取缺少的协议编号 我有我的名单 ProtocolNumber Section -------------------------------- 14A1000014 | A1 14A1000015 | A1 14A1000018 | A1 14A1000019 | A1 14A2000014 | A2 14A2000015 | A2 14A2000
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
它必须是单线选择状态吗 编写一个存储过程或表值函数,使用游标在表中迭代并创建丢失的记录,然后函数返回,怎么样
实施还需要检查每个给定部分的最大协议号,以便您仅创建范围内的记录,假设您正在尝试生成该部分当前存在的最小和最大范围之间缺少的协议号列表,我建议如下:
/*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
缺失协议列表
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
你能提供一个预期的输出吗?什么定义了一个缺失的数字?如果你想检查可能值范围内的所有值,是什么定义了这个范围?我想我的代码是wrong@New_World,您能否提供有关ProtocolNumber字段的一些详细信息?它是否总是等于14+节+6位数?什么定义了6位数字的开始/结束范围?哪些6位数字有效?因为他们有一百万。字面意思。你能给我举个例子吗?请用你的表名替换“协议”。我想你可以在比较Ctetaly和Ranges min/max时去掉“=”。你也可以排除行,除非max min>2。@Beth,我相信你是对的!我经常遇到这样的问题,试图得到所有可能的和任何匹配存在的,但由于OP要求只看到缺失,=符号是多余的。尽管如此,为了简单起见,以及万一需求发生变化以覆盖该场景,我将保持原样。不过,谢谢你指出这一点!