6

問題を単純化する-1から始まり999999までの顧客に番号を割り当てる6桁のフィールドがあります。ほとんどの番号は順番に割り当てられますが、ユーザーは手動で番号を割り当てることができ、この機能は全体を通して予測できないパターンで使用されています。範囲。

ここで、割り当てられていない番号を特定する必要があります(簡単)。次に、これをいくつかの範囲に変換します(複雑なようです)。

たとえば、次の番号が割り当てられている場合

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 Server2008R2を使用しています。これは1回限りの演習であるため、たとえばExcelで簡単に実行できる場合は、SQL以外のソリューションでも適切な場合があります。

4

6 に答える 6

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

参照:itzikben-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
于 2012-11-30T10:01:01.470 に答える
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
于 2012-11-30T10:43:28.610 に答える
1

これがSQLFiddleのデモです

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
于 2012-11-30T10:57:59.147 に答える
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のようなテール範囲は含まれません

于 2012-11-30T10:34:49.193 に答える
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
于 2012-11-30T11:18:35.933 に答える
-1

たとえば、整数のリストである「 myval 」列を持つ「 kh 」というテーブルがある場合は、この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
于 2012-11-30T10:32:26.677 に答える