2010-03-19 6 views
3

Je dois obtenir un compte d'obtenir tous les sous-réseaux distincts dans une colonne IP et le groupe par le sous-réseau sur MS SQL. c'est-à-dire compter tous les ips qui ont un sous-réseau de 192.168.0,192.168.1, 10.10.10 et ainsi de suite.Sous-réseaux distincts de compte SQL dans une colonne IP

Toute aide est appréciée. Merci

+0

Quelle est la structure de stockage de la colonne contenant les adresses IP? –

Répondre

5

Ce n'est pas super efficace, mais en supposant que les adresses sont stockées dans une colonne varchar nommée IPAddress, vous pouvez faire:

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

Cela n'a pas été testé, donc je peut être désactivé par quelque part ou manquant une parenthèse.

L'idée de base est que vous voulez couper la fin en trouvant le dernier point, et pour trouver le dernier point vous inversez plutôt la chaîne et trouvez le premier point, ce que fera CHARINDEX assez facilement. Pour transformer la position "premier point" en position "dernier point" dans la chaîne d'origine, vous soustrayez la position de la longueur d'origine.

(Si mon hypothèse est fausse et il ne sont pas stockées sous forme de texte, vous avez peu de chances d'obtenir une réponse significative à moins que vous donnez aussi le type de données.)

+0

presque à droite. il ne distingue pas entre 192.168.1 et 192.168.2 donner un + 1 (SUBSTRING (IPAddress, 1, LEN (IPAddress) + 1 - CHARINDEX ('.', REVERSE (IPAddress)))) et cela fonctionnera – Coentje

+0

Je suis Désolé, je n'ai pas remarqué ta réponse. – artdanil

+0

@Coentje Vous n'aurez besoin d'ajouter "+1" que si vous souhaitez inclure la chaîne que vous utilisez pour obtenir l'index pour la sous-chaîne. Dans ce cas, le dernier séparateur d'octets n'est pas pertinent. – artdanil

0

En supposant que vous stocker les adresses IP dans le domaine avec varchar ou le type char, la solution pourrait ressembler à ce qui suit:

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))) 

Sur la table:

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 

Produce s résultat suivant:

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

La simple prise des 3 premiers octets ne fonctionnera pas si vous utilisez CIDR. Vous devez faire quelque chose comme ceci

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 
+0

+1 pour l'utilisation d'un CTE et de noms de variables humoristiques mais -1 pour la colonne Count de retour de 2 lorsque seulement 1 IP se trouvait dans ce sous-réseau. – Dane

+0

Je montrais juste un exemple que si vous utilisez des adresses sans classe, couper simplement le dernier octet ne suffira pas. J'ai édité ma réponse pour autoriser les masques de sous-réseau variables –

+0

En effet, et bien fait. – Dane

Questions connexes