Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>This works for me on 8.3 - it should be fine on 8.4 as well. We need a custom aggregate because <code>max(cidr)</code> is not built-in (even though <code>&gt;</code> is)</p> <pre><code>create or replace function greatest_pair(cidr, cidr) returns cidr language 'sql' immutable as $$select greatest($1, $2);$$; create aggregate max( basetype = cidr, sfunc = greatest_pair, stype = cidr ); select max_nb, count(*) from ( select ip, max(nb) as max_nb from netblocks n join iplog i on(i.ip &lt;&lt; n.nb) group by ip ) z group by max_nb; max_nb | count ----------------+------- 192.168.1.0/24 | 2 10.0.0.0/8 | 1 192.168.0.0/16 | 1 </code></pre> <p>If you don't want the custom aggregate, you can do:</p> <pre><code>create or replace view v as select ip, nb from netblocks n join iplog i on(i.ip &lt;&lt; n.nb); select nb, count(*) from ( select * from v o where not exists ( select * from v i where i.ip=o.ip and i.nb&gt;o.nb ) ) z group by nb; </code></pre> <p>or similar using a <code>with</code> clause and no view on 8.4, but the question said <strong>efficiently</strong> :-)</p> <p>tested with these views:</p> <pre><code>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; </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload