我有一个表,其中包含 SQL Server 2005 中的以下字段和示例数据:
id block block_start block_end size
523 10.211.15.16/28 0x0AD30F10 0x0AD30F1F 16
531 10.211.15.36/30 0x0AD30F24 0x0AD30F27 4
532 10.211.15.40/29 0x0AD30F28 0x0AD30F2F 8
533 10.211.15.48/29 0x0AD30F30 0x0AD30F37 8
525 10.211.15.72/29 0x0AD30F48 0x0AD30F4F 8
id是INT标识列。 block是VARCHAR(18),表示CIDR格式的IP块。 block_start和block_end分别是BINARY(4),分别表示块中的第一个和最后一个IPv4地址。大小是块中的IP地址数。
在给定范围的IP和IP数量作为输入的情况下,我需要一种方法来查询第一个可用间隙。例如,我可能希望在 10.211.15.16 和 10.211.15.80 之间找到 4 IP地址的第一个缺失缺口。在此示例中,正确的输出应为10.211.15.32/30(0x0AD30F20至0x0AD30F23)。如果我希望 8 IP地址的第一个间隙在同一范围内,则正确的输出应为10.211.15.56/29(0x0AD30F38到0x0AD30F3F)。
输出为CIDR(varchar)或二进制格式不是问题,因为我有可以在两者之间轻松转换的函数,但我想要查询需要对二进制字段进行。
如果有必要,我可以利用应用程序逻辑(Java或ColdFusion),但如果我能帮助它,我宁愿不这样做。
添加了sqlfiddle:http://sqlfiddle.com/#!3/d45ad
答案 0 :(得分:2)
您可以使用lead()
并将块字段转换为整数来找到差距。像这样:
select t.*
from (select t.*,
cast(lead(block_start) over (order by block_start) as bigint) as nextstart,
cast(block_end as bigint) as thisend
from iptable t
) t
where nextstart - thisend - 1 > @MYNUMBEROFIPS;
如果你想在块上使用范围比较,那就要非常小心。在进行比较之前,您应该将块转换为数值。
编辑:
您可以通过执行以下操作获得等效功能:
select t.*
from (select t.*, cast(block_end as bigint) as thisend,
(select top 1 cast(block_start as bigint)
from iptable t2
where t2.block_start > t.block_start
order by t2.block_start
) as nextstart
from iptable t
) t
where nextstart - thisend - 1 > @MYNUMBEROFIPS;