SQL计算IP列中的不同子网

时间:2010-03-19 14:35:42

标签: sql sql-server

我需要获取一个IP列中所有不同子网的计数,并按MS SQL上的子网进行分组。 ie ..计算所有子网为192.168.0,192.168.1,10.10.10的ips等等。

感谢任何帮助。感谢

3 个答案:

答案 0 :(得分:5)

这不是超级高效,但假设地址存储在名为IPAddress的varchar列中,您可以这样做:

SELECT
    SUBSTRING(IPAddress, 1, LEN(IPAddress) - CHARINDEX('.',REVERSE(IPAddress))),
    COUNT(*)
FROM
    ...
GROUP BY
    SUBSTRING(IPAddress, 1, LEN(IPAddress) - CHARINDEX('.',REVERSE(IPAddress)))

这尚未经过测试,所以我可能会在某个地方离开或错过一个括号。

基本的想法是,你想通过找到最后一个点来切断最后一个点,并找到最后一个点,而不是反转字符串并找到第一个点,CHARINDEX很容易做到。要将“第一个点”位置转换回原始字符串中的“最后一个点”位置,请从原始长度中减去位置。

(如果我的假设是错误的并且没有存储为文本,除非你也提供数据类型,否则你不可能得到有意义的答案。)

答案 1 :(得分:2)

如果您正在使用CIDR,那么简单地取前3个八位字节将无效。你需要做这样的事情

DECLARE @Subnet varchar(15)
DECLARE @bits int
DECLARE @VLSMSuffix int
DECLARE @IP TABLE (IPAddr varchar(15), Running binary(8))

INSERT @IP
SELECT '10.10.19.2', NULL UNION  -- 00001010 00001010 00010011 00000010
SELECT '10.10.10.5', NULL UNION  -- 00001010 00001010 00001010 00000101
SELECT '10.10.11.2', NULL        -- 00001010 00001010 00001011 00000010
SET @Subnet = '10.10.10.0'       -- 00001010 00001010 00001010 00000000
SET @VLSMSuffix = 24             -- # of bits in subnet mask
                                 -- 10.10.11.2 is part of the 10.10.10.0/23 CIDR block
DECLARE @Fun bigint
SET @Fun = CAST(CAST(16777216 as bigint) * PARSENAME(@Subnet, 4) 
                                 + 65536 * PARSENAME(@Subnet, 3) 
                                   + 256 * PARSENAME(@Subnet, 2) 
                                         + PARSENAME(@Subnet, 1) as binary(8))

UPDATE @IP
SET Running = CAST(CAST(16777216 as bigint) * PARSENAME(IPAddr, 4) 
                                    + 65536 * PARSENAME(IPAddr, 3) 
                                      + 256 * PARSENAME(IPAddr, 2) 
                                            + PARSENAME(IPAddr, 1) as binary(8))

-- determine subnet mask
DECLARE @Scissors bigint
SELECT @Scissors = 4294967296 - POWER(CAST(2 AS bigint), CAST(32 AS bigint) - @VLSMSuffix)

SELECT @Subnet [Subnet], COUNT(IPAddr) [Count] 
FROM @IP 
WHERE  @Scissors & Running = @Fun

答案 2 :(得分:0)

假设您将IP地址存储在varcharchar类型的字段中,解决方案可能如下所示:

SELECT 
  "Subnet" = SUBSTRING(IPAddress, 1, LEN(IPAddress) - CHARINDEX('.', REVERSE(IPAddress))),
  "IP Count" = COUNT(*) 
  FROM [tblIPAddress]
  GROUP BY SUBSTRING(IPAddress, 1, LEN(IPAddress) - CHARINDEX('.', REVERSE(IPAddress)))

在桌子上:

IPAddress
-----------------
10.10.10.1
192.168.0.1
192.168.1.2
192.168.1.4
192.168.1.5
192.168.0.2
192.168.0.3
10.10.10.3
127.0.0.1

产生以下结果:

Subnet                                             IP Count
-------------------------------------------------- -----------
10.10.10                                           2
127.0.0                                            1
192.168.0                                          3
192.168.1                                          3