在 table 中查找连续的免费号码

Find consecutive free numbers in table

我有一个 table,包含数字(phone 个数字)和一个代码(免费或不可用)。

现在,我需要找到 30 个连续号码的系列,例如 079xxx100 - 079xxx130,并且所有号码都具有免费状态。

这是我的 table 的示例:

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'),
 ...

我需要一个 SQL 查询,以便在此示例中找到 123200-123230 范围(以及所有下一个可用范围)。

现在,我找到了一个例子,或多或少做了我需要的:

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

但这只返回前 30 个可用数字,不在我的范围内 (0-30)。 (而且执行需要13分钟,呵呵..)

如果有人有想法,请告诉我(我正在使用SQL服务器)

这似乎适用于我的数据集。修改 select 并查看它是否适用于您的 table 名称。

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

这是常见的 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

您可以使用以下 SQL 查询查询 table 预订号码之间的差距数据,其中使用了 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教程Find Missing Numbers and Gaps in a Sequence using SQL

希望对你有所帮助,

目前无法测试,但这可能有效:

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 个连续的号码)