2

这是表结构

table1
pk int, email character varying(100)[]

data
1, {'mr_a@gmail.com', 'mr_b@yahoo.com', 'mr_c@postgre.com'}

我试图实现的是从记录中找到任何“gmail”

query
select * from table1 where any(email) ilike '%gmail%';

但是any()只能在左侧,并且unnest()可能会降低性能。有人知道吗?

编辑

实际上,当我第一次发帖时,我有点困惑。我尝试通过any(array[])来实现。

这是我的实际结构

pk int, 
code1 character varying(100), 
code2 character varying(100), 
code3 character varying(100), ...

我的第一个方法是

select * from tabl1 where code1 ilike '%code%' or code2 ilike '%code%' or...

那我试试

select * from table1 where any(array[code1, code2, ...]) ilike '%code%'

这是行不通的。

4

2 回答 2

5

创建一个实现ILIKE“向后”的运算符,例如:

CREATE FUNCTION backward_texticlike(text, text) RETURNS booleans
    STRICT IMMUTABLE LANGUAGE SQL
    AS $$ SELECT texticlike($2, $1) $$;

CREATE OPERATOR !!!~~* (
    PROCEDURE = backward_texticlike,
    LEFTARG = text,
    RIGHTARG = text,
    COMMUTATOR = ~~*
);

(注意,ILIKE内部对应于操作符~~*。取你自己的反向名称。)

然后你可以运行

SELECT * FROM table1 WHERE '%code%' !!!~~* ANY(ARRAY[code1, code2, ...]);
于 2011-03-26T20:23:34.287 回答
2

将电子邮件地址存储在规范化的表结构中。然后,您可以避免花费unnest,拥有“适当的”数据库设计,并充分利用索引。如果您要进行全文样式查询,您应该将您的电子邮件地址存储在一个表中,然后使用tsvector 数据类型,以便您可以执行全文查询并使用索引。ILIKE '%whatever%'将导致全表扫描,因为计划程序无法利用任何查询。以您目前的设计和足够数量的记录,unnest将是您最省心的事。

更新即使对问题进行了更新,使用标准化代码表也会使您的头痛最小化并导致最佳扫描。每当您发现自己在创建编号列时,这很好地表明您可能想要规范化。话虽如此,您可以创建一个计算文本列以用作搜索词列。在您的情况下,您可以创建一个search_words由触发器在插入和更新时填充的列。然后您可以创建一个tsvectorsearch_words

于 2011-03-21T12:11:01.560 回答