4

我有两列说MainSub。(它们可以是同一张桌子,也可以不是)。

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

我可以成功地设计一个查询来匹配模式使用substr("Main",13,8)

询问:

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

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

问题是我该怎么做。?!

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

Select * from "MainTable"
 Where "MainColumn" Like '%' Select "SubColumn" From "SubTable" Where "SubId"=2'
4

3 回答 3

7

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

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

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

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

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;

两个原因:

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

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

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

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

    该索引支持任一查询。请注意,它会带来一些写入操作的成本。
    此相关答案中类似案例的快速基准

于 2012-07-01T13:28:11.950 回答
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);
于 2012-07-01T10:32:29.883 回答
2

a 的参数LIKE是一个普通的字符串,所以所有的字符串操作在这里都是有效的。在您的情况下,您需要将通配符与目标子字符串连接起来,就像@bksi 建议的那样:

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

但请注意,此类模式(以%通配符开头的模式)性能不佳。看看PostgreSQL LIKE 查询性能变化

我会推荐:

  • 坚持目前的substr("MainColumn", 13, 8)做法;
  • 避免LIKE使用相等比较 ( =) 代替(尽管如果LIKE模式不包含通配符,它​​们是相等的,但更容易阅读查询);
  • 通过以下方式在“MainTable”上构建表达式索引:

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

在我看来,这种组合会表现得更好。

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

于 2012-07-01T11:02:07.457 回答