【问题标题】:Postgress | SQL | Get a row only if the subnet is part of a given ip listPostgreSQL |仅当子网是给定 ip 列表的一部分时才获取一行
【发布时间】:2020-11-25 22:17:17
【问题描述】:

我有一个带有文本列的表格,其中包含带有子网的 ip

| ip
-------------
| 1.1.1.1/30

当您将 1.1.1.1/30 转换为您获得的 ip 列表时:

1.1.1.0
1.1.1.1
1.1.1.2
1.1.1.3

我想在这个表上运行一个 sql 并以某种方式给出一个 ips 列表作为“where”或其他任何东西的一部分,并且只有当我给出的 ips 列表包含范围的 ips 时才获取这一行行。

意义,

where ('1.1.1.0','1.1.1.1) 

--> 我不会得到行

但是:

where ('1.1.1.0','1.1.1.1,1.1.1.2,1.1.1.3) 

--> 我会得到那行

但是:

where ('1.1.1.0','1.1.1.1,1.1.1.2,1.1.1.3,1.1.1.4,1.1.1.5) 

--> 我会得到那行

有没有办法做到这一点?

【问题讨论】:

  • 请注意,/30 可以转换为位掩码,该位掩码可以与二进制形式的 IP 地址进行位与运算,以去除无关紧要的位。比较两个与掩码进行“与”运算的 IP 地址,如果它们都在指定的网络中,则它们将相等。

标签: sql postgresql ip subnet


【解决方案1】:

您必须将 inet 扩展到其所有 host 值,然后使用包含来完成此操作:

with blowout as (
  select t.ip, array_agg(host(network(t.ip::inet) + gs.n)) as all_ips
    from t
   cross join lateral 
         generate_series(0, broadcast(t.ip::inet) - network(t.ip::inet)) as gs(n)
   group by t.ip;
)
select *
  from blowout
 where all_ips <@ array['1.1.1.0', '1.1.1.1', '1.1.1.2', 
                        '1.1.1.3', '1.1.1.4', '1.1.1.5']::text[] 
;

由于您在比较中没有使用任何特殊的inet 函数,因此最好使用text 进行比较。

【讨论】:

    猜你喜欢
    • 2011-09-27
    • 1970-01-01
    • 2018-10-07
    • 1970-01-01
    • 2014-04-15
    • 2016-12-21
    • 1970-01-01
    • 1970-01-01
    • 2019-10-06
    相关资源
    最近更新 更多