在 redshift 中,按 IP 网络分组
In redshift, group by IP network
我想在红移中找到最常被禁止的网络 table。我试过这个:
select network(set_masklen(ip::inet,8)), count(1)
from banlist where status='BLOCKED'
group by 1 order by 2 desc limit 10;
并出现以下错误:
INFO: Function ""network"(inet)" not supported.
INFO: Function "set_masklen(inet,integer)" not supported.
INFO: Function "inet(text)" not supported.
INFO: Function ""network"(inet)" not supported.
INFO: Function "set_masklen(inet,integer)" not supported.
INFO: Function "inet(text)" not supported.
ERROR: Specified types or functions (one per INFO message) not supported on Redshift tables.
OTOH,这个有效:
# select network(set_masklen('10.0.0.1'::inet, 24)); network
-------------
10.0.0.0/24
(1 row)
根据 Redshift 文档,不支持来自 PostgreSQL 的网络地址函数和运算符。
参考文献-
PostgreSQL functions not supported in Redshift
PostgreSQL documentation - Network Address Functions and Operators
虽然其他人关于创建 UDF 的回应可能是一个不错的选择,但如果您愿意放弃一些灵活性并只获得 class A、class B 或class C 子网,您可以使用 SPLIT_PART 和连接运算符来获得(不是超级)快速而肮脏的解决方案。
select
SPLIT_PART(ip_address, '.', 1) || '.' ||
SPLIT_PART(ip_address, '.', 2) || '.' ||
SPLIT_PART(ip_address,'.', 3) as network,
count(1) as mc
from
banlist
group by
network
order by
mc desc
limit 10;
现在这是一个老问题,但我想我会添加我刚刚发现的内容。
@earino 的方法有效,但我还想添加其他两种有效的方法,因为我还需要解决这个聚合问题。
select SPLIT_PART(ip, '.', 1) || '.' || SPLIT_PART(ip, '.', 2) || '.' || SPLIT_PART(ip,'.', 3) || '.0/24' as cidr from banlist;
select REGEXP_REPLACE(ip, '\.[0-9]{1,3}$', '.0/24') as cidr from banlist;
select REGEXP_SUBSTR(ip, '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.') || '0/24' as cidr from banlist;
我不确定哪个表现更好,但我认为正则表达式更容易阅读。
我想在红移中找到最常被禁止的网络 table。我试过这个:
select network(set_masklen(ip::inet,8)), count(1)
from banlist where status='BLOCKED'
group by 1 order by 2 desc limit 10;
并出现以下错误:
INFO: Function ""network"(inet)" not supported.
INFO: Function "set_masklen(inet,integer)" not supported.
INFO: Function "inet(text)" not supported.
INFO: Function ""network"(inet)" not supported.
INFO: Function "set_masklen(inet,integer)" not supported.
INFO: Function "inet(text)" not supported.
ERROR: Specified types or functions (one per INFO message) not supported on Redshift tables.
OTOH,这个有效:
# select network(set_masklen('10.0.0.1'::inet, 24)); network
-------------
10.0.0.0/24
(1 row)
根据 Redshift 文档,不支持来自 PostgreSQL 的网络地址函数和运算符。
参考文献-
PostgreSQL functions not supported in Redshift
PostgreSQL documentation - Network Address Functions and Operators
虽然其他人关于创建 UDF 的回应可能是一个不错的选择,但如果您愿意放弃一些灵活性并只获得 class A、class B 或class C 子网,您可以使用 SPLIT_PART 和连接运算符来获得(不是超级)快速而肮脏的解决方案。
select
SPLIT_PART(ip_address, '.', 1) || '.' ||
SPLIT_PART(ip_address, '.', 2) || '.' ||
SPLIT_PART(ip_address,'.', 3) as network,
count(1) as mc
from
banlist
group by
network
order by
mc desc
limit 10;
现在这是一个老问题,但我想我会添加我刚刚发现的内容。
@earino 的方法有效,但我还想添加其他两种有效的方法,因为我还需要解决这个聚合问题。
select SPLIT_PART(ip, '.', 1) || '.' || SPLIT_PART(ip, '.', 2) || '.' || SPLIT_PART(ip,'.', 3) || '.0/24' as cidr from banlist;
select REGEXP_REPLACE(ip, '\.[0-9]{1,3}$', '.0/24') as cidr from banlist;
select REGEXP_SUBSTR(ip, '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.') || '0/24' as cidr from banlist;
我不确定哪个表现更好,但我认为正则表达式更容易阅读。