Sql 按最小netblock计数记录(间隔)

Sql 按最小netblock计数记录(间隔),sql,postgresql,count,intervals,Sql,Postgresql,Count,Intervals,在SQL(postgresql 8.4.x)中,我如何有效地统计可能包含netblock的最小netblock中的IP记录数?例如,我不想在10/8和0/0下计算10.0.0.1 更具体地说,鉴于: -- CREATE TABLE iplog (ip INET NOT NULL, ...) -- ip | ... ==============+===== 192.168.1.100 | ... 192.168.1.101 | ... 192.168.55.5 | ...

在SQL(postgresql 8.4.x)中,我如何有效地
统计
可能包含netblock的最小netblock中的IP记录数?例如,我不想在
10/8
0/0
下计算
10.0.0.1

更具体地说,鉴于:

-- CREATE TABLE iplog (ip INET NOT NULL, ...)
--
      ip      | ...
==============+=====
192.168.1.100 | ...
192.168.1.101 | ...
192.168.55.5  | ...
10.1.2.3      | ...

-- CREATE TABLE netblocks (nb CIDR UNIQUE NOT NULL, ...)
--
       nb      | ...
===============+======
192.168.1.0/24 | ...
192.168.0.0/16 | ...
10.0.0.0/8     | ...
0.0.0.0/0      | ...
如何高效地生成结果集:

       nb      | ips_logged
===============+============
192.168.1.0/24 | 2
192.168.0.0/16 | 1
10.0.0.0/8     | 1

由于IPv4地址基本上是4字节。您可以创建一个包含netblock_start和netblock_end的表(例如,192.168.1.0/24将是192.168.1.0到192.168.1.255,分别是3232235776到3232235776),然后计算
ip>=netblock_start&ip,因为IPv4地址基本上是4个字节。您可以创建一个包含netblock_start和netblock_end的表(例如,192.168.1.0/24将是192.168.1.0到192.168.1.255,分别是3232235776到3232235776),然后计算
ip>=netblock_start&ip这在8.3上对我有效-在8.4上也应该可以。我们需要自定义聚合,因为
max(cidr)
不是内置的(即使
是内置的)


这在8.3上对我很有效-在8.4上也应该可以。我们需要自定义聚合,因为
max(cidr)
不是内置的(即使
是内置的)

他比我强。为了完整起见,这是我头脑中最天真的想法:

  SELECT nb, COUNT('X')
    FROM netblocks
    JOIN iplog
      ON ip << nb
         AND
         nb = (  SELECT nb
                   FROM netblocks
                  WHERE ip << nb
               ORDER BY nb DESC
                  LIMIT 1)
GROUP BY 1;

       nb       | count 
----------------+-------
 192.168.1.0/24 |     3
 192.168.0.0/16 |     1
 10.0.0.0/8     |     1
(3 rows)
选择nb,COUNT('X')
来自netblocks
加入iplog
在ip上优于对照组。为了完整起见,这是我头脑中最天真的想法:

  SELECT nb, COUNT('X')
    FROM netblocks
    JOIN iplog
      ON ip << nb
         AND
         nb = (  SELECT nb
                   FROM netblocks
                  WHERE ip << nb
               ORDER BY nb DESC
                  LIMIT 1)
GROUP BY 1;

       nb       | count 
----------------+-------
 192.168.1.0/24 |     3
 192.168.0.0/16 |     1
 10.0.0.0/8     |     1
(3 rows)
选择nb,COUNT('X')
来自netblocks
加入iplog

在ip上就是这样做的,但是除非整数被物理地存储在表中,否则它不会有效。Otoh,没有有效的解决方案,包括解析IP。谢谢,Piskvor,但没有必要。
CIDR
INET
类型已经知道它们是有效的:'1.2.3.4'::INET@pilcrow:Ah,我假设它在内部将它们转换为整数,很好。可能是。但要再次提出这个问题:您能否向我展示生成所需结果集的SQL,而不冗余地计算属于多个netblock的IP?这是一种方法,但除非整数以物理方式存储在表中,否则它不会有效。Otoh,没有有效的解决方案,包括解析IP。谢谢,Piskvor,但没有必要。
CIDR
INET
类型已经知道它们是有效的:'1.2.3.4'::INET@pilcrow:Ah,我假设它在内部将它们转换为整数,很好。可能是。但要再次提出这个问题:您是否可以向我展示生成所需结果集的SQL,而不必对属于多个netblock的IP进行冗余计数?+1表示多个解决方案、聚合函数,并且通常以我没有想到的方式处理此问题+1对于多个解决方案,聚合函数,并且通常以我没有想到的方式处理此问题!我想你的问题和我的回答会更适合你——如果你同意的话,你愿意考虑在那里移民吗?我知道你已经有了一个账户…我想你的问题和我的答案会更适合你——如果你同意的话,你愿意考虑在那里移民吗?我看你已经有一个帐户了。。。
create or replace view iplog as
select '192.168.1.100'::inet as ip union all
select '192.168.1.101'::inet union all
select '192.168.55.5'::inet union all
select '10.1.2.3'::inet;

create or replace view netblocks as
select '192.168.1.0/24'::cidr as nb union all
select '192.168.0.0/16'::cidr union all
select '10.0.0.0/8'::cidr union all
select '0.0.0.0/0'::cidr;
  SELECT nb, COUNT('X')
    FROM netblocks
    JOIN iplog
      ON ip << nb
         AND
         nb = (  SELECT nb
                   FROM netblocks
                  WHERE ip << nb
               ORDER BY nb DESC
                  LIMIT 1)
GROUP BY 1;

       nb       | count 
----------------+-------
 192.168.1.0/24 |     3
 192.168.0.0/16 |     1
 10.0.0.0/8     |     1
(3 rows)