Postgresql:两列之间的匹配模式

时间:2012-07-01 10:03:19

标签: postgresql pattern-matching

我有两栏说MainSub。 (他们可以是同桌或不同)。

Main是长度为20的varchar,Sub是长度为8的varchar Sub 始终 <{1}}的子集,并且是Main的最后8个字符。

我可以使用Main

成功设计一个匹配模式的查询

查询:

substr("Main",13,8)

但我想在我的查询中使用Like,%,_ etc,以便我可以松散地匹配模式(不是全部8个字符)。

问题是我该怎么做。?!

我知道下面的查询是完全错误,但我想实现这样的目标,

select * from "MainTable"
 where substr("MainColumn",13,8) LIKE (
   select "SubColumn" From "SubTable" Where "SubId"=1043);

3 个答案:

答案 0 :(得分:5)

到目前为止,答案未能解决您的问题:

  

但是我想在我的查询中使用Like,%,_ etc以便我可以松散匹配   模式(不是全部8个字符)。

只要您匹配整个字符串(并且字符串中没有通配符),您使用LIKE=几乎没有任何区别。要使搜索模糊,您需要替换模式的一部分,而不仅仅是添加它。

例如,匹配subcolumn的最后7个(而不是8个)字符:

SELECT *
FROM   maintable m
WHERE  left(maincolumn, 8) LIKE 
       ( '%' || left((SELECT subcolumn FROM subtable WHERE subid = 2), 7));

我使用更简单的left()(Postgres 9.1引入) 您could将此简化为:

SELECT *
FROM   maintable m
WHERE  left(maincolumn, 7) =
       (SELECT left(subcolumn,7) FROM subtable WHERE subid = 2);

但如果你使用我进一步提到的特殊索引,你就不会这样做,因为功能索引中的表达式必须精确匹配才能使用。

您可能对扩展程序pg_tgrm感兴趣。

在PostgreSQL 9.1中,每个数据库运行一次:

CREATE EXTENSION pg_tgrm;

有两个原因:

  • 它提供similarity operator %。有了它,您可以构建智能相似性搜索:

    --SELECT show_limit();
    SELECT set_limit(0.5); -- adjust similarity limit for % operator
    
    SELECT *
    FROM maintable m
    WHERE left(maincolumn, 8) %
          (SELECT subcolumn FROM subtable WHERE subid = 2);
    
  • LIKE%提供index support

    如果读取性能比写入性能更重要,我建议您创建一个functional GIN或GiST索引,如下所示:

    CREATE INDEX maintable_maincol_tgrm_idx ON maintable
    USING gist (left(maincolumn, 8) gist_trgm_ops);
    

    此索引支持任一查询。请注意,它会带来一些写入操作的成本 A quick benchmark for a similar case in this related answer

答案 1 :(得分:2)

尝试

SELECT t1.* from "Main Table" AS t1, "SubTable" AS t2
 WHERE t2.SubId=1043
   AND substr(t1.MainColumn, 13, 8) LIKE "%" || CAST(t2.SubColumn as text);

答案 2 :(得分:2)

LIKE的参数是普通字符串,因此所有字符串操作在此处都有效。 在你的情况下,你需要将wildchars连接到目标子字符串,如@bksi建议:

... LIKE '%'||CAST("SubColumn" AS test) ...

但请注意,这些模式(以%通配符开头的模式)表现不佳。看看PostgreSQL LIKE query performance variations

我建议:

  • 坚持使用当前substr("MainColumn", 13, 8)方法;
  • 避免使用LIKE并使用相等比较(=)(尽管如果LIKE模式不包含通配符,它​​们相等,则更容易阅读查询);
  • 通过以下方式在“MainTable”上构建expression index

    CREATE INDEX i_maincolumn ON "MainTable" (substr("MainColumn", 13, 8));
    

在我看来,这种组合效果会更好。

并为表/列使用小写名称,这样就可以避免双重命名。