我有两栏说Main
和Sub
。 (他们可以是同桌或不同)。
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);
答案 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));
在我看来,这种组合效果会更好。
并为表/列使用小写名称,这样就可以避免双重命名。