postgres |如何根据精确或更少的ip列表和简单的文本列表获取行

0s7z1bwu  于 2021-07-24  发布在  Java
关注(0)|答案(2)|浏览(352)

我有一个包含两个文本列的表:type和ip。它们可以是单个文本,也可以是多个文本,用“@##@”分隔。此外,ip也可以是1.1.1.1/24等范围
下表

row |type       | ip
-------------------------------------------
1   |red           | 1.1.1.1
2.  |red@##@blue   | 1.1.1.1@##@2.2.2.2
3.  |blue          | 1.1.1.1/32@##@2.2.2.2/32
4.  |yellow        | 1.1.1.1
5.  |red           | 3.3.3.3
6.  |yellow@##@red | 1.1.1.1
7.  |blue          | 1.1.1.1@##@3.3.3.3

我想得到所有类型为red或blue或两者(确切地说是red和blue或更少,意思是一个红色或一个蓝色)和ip 1.1.1.1或2.2.2.2或两者都包括范围的行(确切地说是1.1.1.1和2.2.2.2或更少,意思是一个1.1.1或一个2.2.2,或者如果我们有多个ip,它们需要匹配范围ecactly或更少)
意思是我想得到第1,2,3行
我开始编写下一个查询,但无法正确执行:

SELECT * FROM t where
    regexp_split_to_array(t.type, '@##@')::text[] in ('red','blue')
    and
    regexp_split_to_array(t.ip, '@##@')::inet[] in ('1.1.1.1','2.2.2.2')

提前谢谢!

j1dl9f46

j1dl9f461#

需要重叠运算符:

SELECT *
FROM t
WHERE regexp_split_to_array(t.type, '@##@')::text[] && array['red', 'blue'] and
      regexp_split_to_array(t.ip, '@##@')::inet[] && array['1.1.1.1', '2.2.2.2']
o8x7eapl

o8x7eapl2#

匹配 type 这样,一个,另一个,或者两者都可以通过包含操作符来完成,因为基本的比较是相等的。
匹配 inet 类型到子网是另一回事。必须使用
inet && 运算符(contains或is contained by),因此 ip 数组必须由 unnest . 再次匹配一个、另一个或两者的要求意味着我们需要 ip 仅当匹配项的计数等于 ip 价值观。
此查询似乎可以完成此任务。在这儿摆弄。

with asarrays as (
  SELECT row, regexp_split_to_array(t.type, '@##@')::text[] as types,
         unnest(regexp_split_to_array(t.ip, '@##@')::inet[]) as ip
    FROM t
), typematch as (
  select *, count(*) over (partition by row) as totcount
    from asarrays 
   where types <@ array['red', 'blue']
), ipmatch as (  
  select *, count(*) over (partition by row) as matchcount
    from typematch
   where ip && any(array['1.1.1.1'::inet, '2.2.2.2'::inet])
)
select row, types, array_agg(ip) as ip 
  from ipmatch
 where matchcount = totcount
 group by row, types;

相关问题