简化我的问题 - 我有6位数的字段,从1开始到999999为客户分配号码。大多数号码是按顺序分配的,但是号码可以由用户手动分配,并且此功能已用于整个范围内的不可预测的模式。
我们现在需要识别尚未分配的数字(简单) - 然后将其转换为多个范围(看起来很复杂)。
例如,鉴于已指定以下数字
1,2,3,4,5,
1001,1002,1003,1004,1005,
999101,999102,999103,999104,999105
我需要一组结果范围,例如
Start End
6 1000
1006 999100
999106 999999
到目前为止,我的想法是,在查询中写入可能过于复杂 - 最好通过循环从1到999999,并将范围添加到临时表。
有兴趣听到我能想象的想法有一些方法。我正在使用SQL Server 2008 R2。这是一次性练习,因此即使是非SQL解决方案也可能是合适的,例如,如果这可以在Excel中轻松完成。
答案 0 :(得分:5)
试试这个
declare @t table (num int)
insert @t values (2),(3),(6),(7),(9),(10),(11)
select
MIN(number) as rangestart,
MAX(number) as rangeend
from
(
select *,
ROW_NUMBER() over (order by number) -
ROW_NUMBER() over (order by num,number) grp
from
(
select number from master..spt_values where type='p' and number between 1 and 15
) numbers
left join @t t
on numbers.number = t.num
) v
where num is null
group by grp
参考:itzik ben-gan的空白和岛屿
创建高达999999的数字查询
select p1.number + p2.number * 2048 as number
from
(select * from master..spt_values where type='p' ) p1,
(select * from master..spt_values where type='p' and number<489) p2
where p1.number + p2.number * 2048 <=999999
答案 1 :(得分:2)
declare @t table (num int)
insert @t values
(2),(3),(4),(5),
(1001),(1002),(1003),(1004),(1005),
(999101),(999102),(999103),(999104),(999105)
;with cte as
(
select num,(ROW_NUMBER() OVER(ORDER BY num)) + 1 as idx from @t
union
select 0 [num],1 [idx] --start boundary
union
select 1000000 [num],COUNT(num) + 2 [idx] from @t --end boundary
)
select c1.num + 1 [Start], c2.num - 1 [End]
from cte c1
inner join cte c2 on c2.idx = c1.idx + 1
where c2.num != c1.num + 1
答案 2 :(得分:1)
create table #temp (id int)
insert into #temp (id)
values (1),(2),(3),(1000),(1001),(1002),(2000)
--drop table #temp
with cte as
(
select *, ROW_NUMBER() over(order by id) as rn
from #temp a
)
select a.id + 1, b.id - 1
from cte a join cte b on a.rn = b.rn - 1 and a.id <> b.id -1
它不包括尾部范围,如2001-9999
答案 3 :(得分:1)
select
case when max(n1)=0 then 1 else max(n1)end,
case when max(n2)=0 then 999999 else max(n2)end
from
(
select t.n+1 as n1,0 n2,
row_number() over(order by t.n)
+isnull((select 0 from t where n=1),1)
rn
from t
left join t t2 on t.n+1=t2.n
where t2.n is null
union all
select 0 n1, t.n-1 as n2 ,
row_number() over(order by t.n) rn
from t
left join t t2 on t.n-1=t2.n
where t2.n is null
and t.n>1
) t3
group by rn
答案 4 :(得分:1)
declare @t table(id int)
insert @t values
(1),(2),(3),(4),(5),(1001),(1002),(1003),(1004),(1005),
(999101),(999102),(999103),(999104),(999105)
select t1.id+1 [start], coalesce(t3.[end], 999999) [end]
from @t t1
left join @t t2 on t1.id +1 = t2.id
cross apply
(select min(id)-1 [end] from @t where t1.id < id
) t3
where t2.id is null
答案 5 :(得分:-1)
如果您有一个名为“ kh ”的表格,例如列“ myval ”,这是您的整数列表,您可以尝试此SELECT。
SELECT MAX(t1.myval+1) AS 'StartRange',t3.myval-1 AS 'EndRange'
FROM kh t1, kh t3
WHERE t1.myval+1 NOT IN (SELECT myval FROM kh t2 ORDER BY myval)
AND t3.myval-1 NOT IN (SELECT myval FROM kh t4 ORDER BY myval)
AND t1.myval < t3.myval
GROUP BY t3.myval
ORDER BY StartRange