Интересный запрос по базе IP-адресов

Richard NN
Дата: 21.05.2004 18:18:56
Есть таблица c полем srcaddr (cidr), внутри IP-адреса с маской /32
srcaddr
-------
212.23.24.110/32
212.23.23.112/32
81.18.124.11/32

Каким образом в результате выполнения запроса можно сгруппировать значения так чтобы получить только адреса сетей.Например так:
212.23.24.0/24
81.18.124.0/24 и т.д.
serega2k
Дата: 22.05.2004 02:46:33
SELECT FROM <имя таблицы> 
          WHERE srcaddr LIKE '%.0___'
          GROUP BY srcaddr
Richard NN
Дата: 24.05.2004 11:35:29
ERROR: Unable to identify an operator '~~' for types 'cidr' and '"unknown"'
You will have to retype this query using an explicit cast

Суть такова что LIKE не работает с типом данных cidr.
Еще этот запрос не подходит т.к. в базе нет адресов сетей типа '%.0/24',а есть только IP адреса... интересно то как получить все адреса сетей имея только IP адреса.
Shweik
Дата: 24.05.2004 12:19:01
Думаю так как нет никаких предопределенных функций то
стоит попробовать что-то такое:
tst=> SELECT ip FROM t1
WHERE ip::text LIKE '%.26.%'
GROUP BY ip;
В contribe я ничего готового необнаружил - народ видимо и так обходится.
Впрочем у меня таких задач небыло - мож знатоки чего подскажут .
Richard NN
Дата: 24.05.2004 13:07:15
ERROR: Cannot cast type cidr to text

Невозможно преобразование cidr в текст. Есть идея, что можно организовать битовый сдвиг до вида 192.168.3.0 (из значений вида 192.168.3.5 , 192.168.3.6 и т.п.) и поместить в отдельную таблицу недублирующиеся элементы.
Тогда появляется новый вопрос. Как можно организовать битовый сдвиг IP адресов на 8 последних битов....
Richard NN
Дата: 24.05.2004 14:18:20
Вроде как нашел выход из этой проблемы....

select distinct network(set_masklen(srcaddr,24)) from log;

сначала проставляем что все адреса это адреса сети, а потом получаем на выходе требуемые значения...

set_masklen(inet, integer) -- set_masklen('192.168.1.5/24', 16) -- 192.168.1.5/16

network(inet) -- network('192.168.1.5/24') -- 192.168.1.0/24
Wireless
Дата: 24.05.2004 14:29:08
все гениальное просто ;)

select network((ipt.ip::text||'/24')::inet) as net, count(*)
from iptable ipt
group by 1

если будет возникать ошибка вида
ERROR: invalid input syntax for type inet: "162.33.177.12/32/24"

то запрос нужно будет переписать на такой

select network((substr(ipt.ip::text, 1, length(ipt.ip::text) -3)||'/24')::inet) as net, count(*)
from iptable ipt
group by 1

дерзай..
Richard NN
Дата: 24.05.2004 14:32:12
Спасибо всем! Разобрался!

ЗЫ Действительно все гениальное просто!
Wireless
Дата: 24.05.2004 14:40:23
Не видел твой последний пост, да, с set_masklen красивее...