Bo *_*nes 8 postgresql pattern-matching array
给定一个可能包含多个分隔符实例的字符串,我想生成从该字符开始的所有子字符串。
例如,给定一个像'a.b.c.d.e'
(或 array {a,b,c,d,e}
,我想)这样的字符串,我想生成一个像这样的数组:
{a.b.c.d.e, b.c.d.e, c.d.e, d.e, e}
Run Code Online (Sandbox Code Playgroud)
预期用途是作为填充一列的触发器,以便在写入另一列时更容易地查询域名部分(即,查找全部q.x.t.com
以进行查询t.com
)。
解决这个问题似乎是一种笨拙的方法(而且很可能是),但现在我很好奇如何用(Postgres')SQL 编写这样的函数。
这些是电子邮件域名,因此很难说元素的最大可能数量是多少,但绝大多数肯定会小于 5。
我想这是我的最爱。
create table t (id int,str varchar(100));
insert into t (id,str) values (1,'a.b.c.d.e'),(2,'xxx.yyy.zzz');
Run Code Online (Sandbox Code Playgroud)
select id
,array_to_string((string_to_array(str,'.'))[i:],'.')
from t,unnest(string_to_array(str,'.')) with ordinality u(token,i)
;
Run Code Online (Sandbox Code Playgroud)
+----+-----------------+
| id | array_to_string |
+----+-----------------+
| 1 | a.b.c.d.e |
| 1 | b.c.d.e |
| 1 | c.d.e |
| 1 | d.e |
| 1 | e |
| 2 | xxx.yyy.zzz |
| 2 | yyy.zzz |
| 2 | zzz |
+----+-----------------+
Run Code Online (Sandbox Code Playgroud)
select id
,array_agg(array_to_string((string_to_array(str,'.'))[i:],'.'))
from t,unnest(string_to_array(str,'.')) with ordinality u(token,i)
group by id
;
Run Code Online (Sandbox Code Playgroud)
+----+-------------------------------------------+
| id | array_agg |
+----+-------------------------------------------+
| 1 | {"a.b.c.d.e","b.c.d.e","c.d.e","d.e","e"} |
| 2 | {"xxx.yyy.zzz","yyy.zzz","zzz"} |
+----+-------------------------------------------+
Run Code Online (Sandbox Code Playgroud)
我认为您不需要在这里单独开设专栏;这是一个 XY 问题。您只是想进行后缀搜索。有两种主要方法可以对其进行优化。
基本上,你可以通过逆转一切来做到这一点。
首先在列的背面创建一个索引:
CREATE INDEX ON yourtable (reverse(yourcolumn) text_pattern_ops);
Run Code Online (Sandbox Code Playgroud)
然后使用相同的查询:
SELECT * FROM yourtable WHERE reverse(yourcolumn) LIKE reverse('%t.com');
Run Code Online (Sandbox Code Playgroud)
UPPER
如果你想让它不区分大小写,你可以抛出一个调用:
CREATE INDEX ON yourtable (reverse(UPPER(yourcolumn)) text_pattern_ops);
SELECT * FROM yourtable WHERE reverse(UPPER(yourcolumn)) LIKE reverse(UPPER('%t.com'));
Run Code Online (Sandbox Code Playgroud)
另一个选项是三元组索引。LIKE 'something%something'
如果您需要中缀查询(或LIKE '%something%'
类型查询),您绝对应该使用它。
首先启用 trigram 索引扩展:
CREATE EXTENSION pg_trgm;
Run Code Online (Sandbox Code Playgroud)
(这应该是 PostgreSQL 开箱即用的,无需任何额外安装。)
然后在您的列上创建一个三元组索引:
CREATE INDEX ON yourtable USING GIST(yourcolumn gist_trgm_ops);
Run Code Online (Sandbox Code Playgroud)
然后只需选择:
SELECT * FROM yourtable WHERE yourcolumn LIKE '%t.com';
Run Code Online (Sandbox Code Playgroud)
同样,如果您愿意,您可以添加一个UPPER
以使其不区分大小写:
CREATE INDEX ON yourtable USING GIST(UPPER(yourcolumn) gist_trgm_ops);
SELECT * FROM yourtable WHERE UPPER(yourcolumn) LIKE UPPER('%t.com');
Run Code Online (Sandbox Code Playgroud)
三元组索引实际上使用您所要求的更通用的形式来工作。它将字符串分解成片段(三元组)并基于这些片段构建索引。然后,索引可用于比顺序扫描更快地搜索匹配项,但适用于中缀以及后缀和前缀查询。尽可能避免重新发明别人开发的东西。
这两个解决方案几乎都是来自选择 PostgreSQL 文本搜索方法。我强烈建议您阅读它,以详细分析 PotsgreSQL 中可用的文本搜索选项。
归档时间: |
|
查看次数: |
1100 次 |
最近记录: |