根据标记交集获取类似的行

时间:2014-12-17 00:58:19

标签: sql arrays postgresql

给定一个包含2个cols的表,id(bigserial)和tags(varchar(64)[])

id|tags
--------
1 |a,b,c
2 |a,c
3 |d,e

根据标签交集计数(ic)获取行的最佳查询是什么?

所以搜索a,b,c将返回

id|ic
-----
1 |3
2 |2
3 |0

2 个答案:

答案 0 :(得分:1)

SELECT t.id, count(tag = ANY ('{a,b,c}') OR NULL) AS ic
FROM   tbl t
     , unnest(tags) x(tag)
GROUP  BY 1;

那是implicit JOIN LATERAL。排除带有空数组或NULL数组的行。要包含,请使用:

LEFT JOIN unnest(tags) x(tag) ON TRUE

OTOH,如果您只对至少有一个匹配的行感兴趣,可以使用overlap array operator &&预先选择以获得更好的效果:

SELECT t.id, count(tag = ANY ('{a,b,c}') OR NULL) AS ic
FROM  (SELECT * tbl WHERE tags && '{a,b,c}') t
     , unnest(tags) x(tag)
GROUP  BY 1;
GIN索引可以支持

&&,这对于一个大表来说会有所不同。

有关计数技术的更多信息:

答案 1 :(得分:0)

SELECT id, IF(('a' = ANY(tags)),1,0) + IF(('b' = ANY(tags)),1,0) + IF(('c' = ANY(tags)),1,0) AS ic
FROM mytable