2012-06-03 29 views
4

我需要按子網(前3個八位字節)對IP列表進行分組來計數。舉例來說,如果我有Ips的如何在MySQL中通過子網對IP列表進行分組?

123.12.12.12 
123.12.12.11 
123.12.11.11 

我一定要得到這樣的結果:

123.12.12 | 2 
123.12.11 | 1 

我GOOGLE了這個expample:

select 
substr(ip,1,locate('.',ip,locate('.',ip)+1)-1) 
as ip, count(ip) as count 
from ip_list 
group by ip ORDER BY count DESC 

但組的列表只有兩個字節。我在所有這些locate(locate(locate(...)))中都輸了。有人可以幫助修改這個來獲得正確的結果嗎?

+0

123.0.0.0是A類,所以(默認)子網掩碼是255.0.0.0,而不是255.255.255.0 –

回答

7

你應該使用group by表達名字

select 
-- locate('.', ip, locate('.', ip, locate('.', ip) + 1) + 1) as l, 
    substr(ip, 1, locate('.', ip 
          , locate('.', ip 
            , locate('.', ip) + 1) + 1) - 1) as subip, 
    count(ip) as count 
from ip_list 
group by (subip) 
order by count desc 
; 

編輯1
不需要 使用locate。可以使用SUBSTR_INDEX來過濾IP的子集。

select 
     substring_index(ip, '.', 3) as subip 
    , count(ip) as count 
    from ip_list 
group by (subip) 
order by count desc 

參見文檔:長

+0

只需要添加'substring_index(ip,',',3)'將是一種更加優雅的切割方式IP的最後部分,而不是使用substr()和locate()。 – Botch

+1

@Botch:的確如此。答案只是爲了解決這個問題。現在添加一個替代解決方案。 –

1

使用這個邏輯我怕你會需要的locate還有另一層:

substr(ip, 1, locate('.', ip, locate('.', ip, locate('.', ip)+1) +1) - 1) 
1

你可以使用

GROUP BY INET_ATON(ip)/256 
0

如果做了IP二進制,你可以申請在這面具只保留前3個部分您的IP地址。面具看起來是這樣的:

11111111111111111111111100000000 

所以,作爲一個數字,它看起來像:

SELECT CONV('11111111111111111111111100000000' ,2,10) as mask; 
-- Result: 4294967040 

如果你做了位與在用這種面膜您的IP地址,你會得到這樣一個結果這樣的:

SELECT 
'1.0.207.199',     
INET_NTOA(INET_ATON('1.0.207.199') & 4294967040) ; 
-- Result: 
-- 1.0.207.199 
-- 1.0.207.0 

INET_ATON轉換的IP(A)ddress(TO)一(N)棕土,以及INET_NTOA反之亦然(儘管真正意義上的代表ASCII網絡,但我喜歡這個shofthand更好;-) 。

所以,你可以用你的IP地址組這樣的:

SELECT 
    INET_NTOA(INET_ATON(ip) & 4294967040) AS ipgroup, 
    COUNT(ip) AS count 
FROM ip_list 
GROUP BY ipgroup 
ORDER BY count DESC; 

我希望它能幫助。

相關問題