一个人可以有多个标签, sql 筛选只包含某些标签[标签(1,2,3)]的人,怎么写效率高?

2021-04-16 16:33:56 +08:00
 yusheng88
一个人可以有多个标签, sql 筛选只包含某些标签[标签(1,2,3)]的人,怎么写效率高?
表:person_tag
字段 : id , person_id , tag_id

我的实现逻辑是:
先筛选出拥有这些标签的人,再排除其中不只有这些标签的人。
感觉还有更好的实现逻辑。

with w1 as (
select distinct person_id
from person_tag
where tag_id in(1,2,3)
),w2 as (
select distinct w1.person_id
from w1
left join person_tag t1
on w1.person_id=t1.person_id and t1.tag_id in(1,2,3)
where t1.id is null
)
select person_id from w1
except
select person_id from w2

-- select person_id
-- from w1
-- where not exists (
-- select 1
-- from w2
-- where w1.person_id = w2.person_id
-- )
948 次点击
所在节点    问与答
7 条回复
FakNoCNName
2021-04-16 17:58:33 +08:00
```
SELECT *
FROM person_tag
WHERE tag_id = '1' OR tag_id = '2' OR tag_id = '3'
GROUP BY person_id
HAVING count(person_id) = 3;
```
yushiro
2021-04-16 19:26:09 +08:00
@FakNoCNName 你这语句是错的,如果有人是 1,2,4 这样的,也会 select 出来
xupefei
2021-04-16 19:41:29 +08:00
如果你用 spark sql 的话,array_length(array_intersect(col, array(1,2,3)))=3 能满足你的需求
FakNoCNName
2021-04-16 20:30:46 +08:00
@yushiro 原理还是这个原理,题主可以自己优化下
optional
2021-04-17 08:12:58 +08:00
pg text[] 欢迎你
yusheng88
2021-04-17 10:24:54 +08:00
@xupefei 现在只是使用 mysql,数据库不支持数组函数,这个实现逻辑很好,感觉效率会更高,如果是使用 postgresql,应该也能实现
yusheng88
2021-04-17 11:39:50 +08:00
@xupefei 感谢大佬,想到了 pg 数据库的实现,实测有提升,sql 如下:

select t1.person_id
from person_tag t1
join person_tag t2
on t1.person_id=t2.person_id
and t1.tag_id in(1,2,3)
group by t1.person_id
having array_agg( t2.tag_id ) <@ array[1,2,3]

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/771122

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX