今天受益匪浅,抛砖引出了大神的玉。
我的砖如下:
A表,字段有id,name和words,words字段以"|"为分隔符,如下:
B表,字段为words和numbers,但是words字段有所不同,具体如下:
需求为:通过表B中的“董事”或者“投资”或者“债券”或者其他词,此处我们默认按B表的number字段排序,limit3,然后去表A匹配出包含它们的记录。
开发同事表示,如果先从B表把words取出来,然后在后台循环列表,比较麻烦,能否在一个sql语句中把记录查出来?
我思考了一下,觉得用数组可以解决,于是语句如下:
select * from A
where words like '%'||(select b[1] from (
select array(select words from B order by number desc limit 3) as b
) a)||'%'
or words like '%'||(select b[2] from (
select array(select words from B order by number desc limit 3) as b
) a)||'%'
or words like '%'||(select b[3] from (
select array(select words from B order by number desc limit 3) as b
) a)||'%' limit 6
子查询为select array(select words from B order by number desc limit 3),即先把前三个组成数据,然后取别名为b,再分别取b中值拼接like语句,最终达成效果。
实现是实现了,但是语句很丑。
大神看到后说,PG给数组提供一堆数组操作相关的函数和操作符,以及索引方法。
其实使用数组的操作符,就可以解决,语句如下:
select * from A where regexp_split_to_array(words,'\|') && array(select words::text from B order by number desc limit 3);
简洁,高效。如果把A表的words字段类型改为数组类型,再建立gin或者gist索引,以后数据量大了,效率也会更高。