2016-04-06 12 views
4

数字(電話番号)とコード(空きありません)を含むテーブルがあります。テーブルで連続した空き番号を見つけよう

ここでは、079xxx100 - 079xxx130のような30個の連続した数字のシリーズを見つけて、それらのすべてがフリーステータスになるようにする必要があります。私は、この例では123200から123230の範囲(およびすべての次の使用可能な範囲を)私を取得するには、SQLクエリを必要とする

CREATE TABLE numere 
(
    value int, 
    code varchar(10) 
); 


INSERT INTO numere (value,code) 
Values 
(123100, 'free'), 
(123101, 'free'), 
... 
(123107, 'booked'), 
(123108, 'free'), 
(... 
(123130, 'free'), 
(123131, 'free'), 
... 

(123200, 'free'), 
(123201, 'free'), 
... 
(123230, 'free'), 
(123231, 'free'), 
... 

:ここ

は次のように私のテーブルがどのように見えるかの例です。

は今、私は私が必要なもの、多かれ少なかれやって、例を見つけました:

select value, code 
from numere 
where value >= (select a.value 
       from numere a 
       left join numere b on a.value < b.value 
            and b.value < a.value + 30 
            and b.code = 'free' 
       where a.code = 'free' 
       group by a.value 
       having count(b.value) + 1 = 30) 
limit 30 

が、これは私の範囲(0-30)内のみ最初の30の可能な番号を返す、とされていません。誰もがアイデアを持っている場合

(と..笑、実行するために13分かかります)、(私はSQL Serverを使用しています)

答えて

2

私に知らせて、それは私のデータセットで動作するようにこれが思わしてください。選択を修正し、テーブル名で動作するかどうかを確認します。

DECLARE @numere TABLE 
(
value int, 
code varchar(10) 
); 


INSERT INTO @numere (value,code) SELECT 123100, 'free' 

WHILE (SELECT COUNT(*) FROM @numere)<=30 
BEGIN 
    INSERT INTO @numere (value,code) SELECT MAX(value)+1, 'free' FROM @numere 
END 

UPDATE @numere 
SET code='booked' 
WHERE value=123105 

select * 
from @numere n1 
inner join @numere n2 ON n1.value=n2.value-30 
    AND n1.code='free' 
    AND n2.code='free' 
LEFT JOIN @numere n3 ON n3.value>=n1.value 
    AND n3.value<=n2.value 
    AND n3.code<>'free' 
WHERE n3.value IS NULL 
+0

感謝を持っているすべての数字である必要があり、これは私の30個の連続した空き番号を見つけ、正常に動作します。 00-30の範囲からしか見つけることはできませんので、私は手作業で行います。 誰かが00からそれらを見つける簡単な方法を持っていれば(最後の数字を切り捨てて、それらが0-30の範囲内にあるかどうかをチェックする、substr関数のように思えるでしょう) –

+0

あなたのコメントの後半部分を理解していません。どのようにパフォーマンスが元々使っていた方法と比較したのですか? – UnhandledExcepSean

+0

性能に関して、私はダミーのsqliteデータベースでしかテストしていません。明日は本番データベースで確認しますが、それは多かれ少なかれ同じ性能です。私のコメント、これは実際の使用事例で、一部の企業(30人の雇用者を持つ)は079xxxx00-079xxxx30のような数字をすべて持ちたいと思っています(最後の2桁、0から30まで)、データベースから選択する必要があります、無料の番号がある場合は、この範囲内 anywhay、あなたの答えはそれがそうであるように、すでに極端にusmefulです。ありがとう –

1

これは通常のIsland and Gapの問題です。

; with cte as 
( 
    select *, grp = row_number() over (order by value) 
      - row_number() over (partition by code order by value) 
    from numere 
), 
grp as 
(
    select grp 
    from cte 
    group by grp 
    having count(*) >= 30 
) 
select c.grp, c.value, c.code 
from grp g 
    inner join cte c on g.grp = c.grp 
1

あなたはSQLチュートリアルFind Missing Numbers and Gaps in a Sequence using SQL

を確認することができますSQL LEAD() analytical function

;with cte as (
select 
    value, lead(value) over (order by value) nextValue 
from numere 
where code = 'booked' 
), cte2 as (
select 
value gapstart, nextValue gapend, 
(nextValue - value - 1) [number count in gap] from cte 
where value < nextValue - 1 
) 
select * 
from cte2 
where [number count in gap] >= 30 

を使用している次のSQLクエリを使用して予約した数字の間のギャップのために表データを照会することができ、私はそれが役に立てば幸い、

1

現時点ではテストできませんが、これはうまくいく可能性があります:

SELECT a.Value FROM (SELECT Value FROM numere WHERE Code='free' ) a INNER Join (SELECT Value FROM numere WHERE code='free' ) b ON b.Value BETWEEN a.Value+1 AND a.Value+29 GROUP BY a.Value HAVING COUNT(b.Value) >= 29 ORDER BY a.Value ASC

出力は、以下の29個の無料の番号(それは30個の連続した数字です)

+0

ありがとう、この1つは、値だけでなく、コードを表示する(私は非常にSQLに新しいですが、私は変更しようとするので、私は出力になる両方の列)。 –

関連する問題