【问题标题】:how to do 'any(::text[]) ilike ::text'怎么做'any(::text[]) ilike ::text'
【发布时间】:2011-03-21 11:15:08
【问题描述】:

这是表结构

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%'

这不起作用。

【问题讨论】:

    标签: postgresql conditional-statements string-comparison any


    【解决方案1】:

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

    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, ...]);
    

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

      • 感谢您的建议。其实我是泰国人。 db 数据是泰语的,由于单词和语言的复杂性与 Eng 完全不同,泰语的全文搜索工作非常糟糕。我已经尝试过您的解决方案,它在英语中很棒。但是当我在泰语中尝试它时效果不佳。您的数据库优化建议真的很有帮助。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-11-22
      • 2021-11-11
      • 2013-06-11
      • 2016-07-07
      • 1970-01-01
      • 2015-06-08
      • 2022-01-21
      相关资源
      最近更新 更多