我想出了这个查询,找到所有标记了某个标记列表的人:
select * from people
where ARRAY[?]::character varying[] <@ ARRAY(
select tags.name
from tags
inner join taggings on tags.id = taggings.tag_id
where taggings.taggable_type = 'Person' and
taggings.taggable_id = people.id)
不知怎的,我觉得我让事情变得太复杂了。目前我们没有足够的数据来表现不佳,但是真的没有更好的方法吗?
编辑:最小的表格定义:
create table people (
id integer
);
create table tags (
id integer,
name text
);
create table taggings (
id integer,
tag_id integer,
taggalbe_type text,
taggable_id integer
);
最小数据:
insert into people values (1);
insert into people values (2);
insert into people values (3);
insert into tags values (1, 'foo');
insert into tags values (2, 'bar');
insert into tags values (3, 'baz');
insert into taggings values (1, 1, 'Person', 1);
insert into taggings values (2, 2, 'Person', 1);
insert into taggings values (3, 1, 'Person', 2);
insert into taggings values (4, 2, 'Person', 2);
insert into taggings values (5, 3, 'Person', 2);
现在我想要,例如标有foo
和bar
的所有人。那个例子就是id为2的人。
答案 0 :(得分:1)
select p.id, array_agg(t.name) as tag_name
from
people p
inner join
taggings g on p.id = g.taggable_id
inner join
tags t on g.tag_id = t.id
where g.taggable_type = 'Person'
group by p.id
having array['foo','bar']::text[] <@ array_agg(t.name)
;
id | tag_name
----+---------------
1 | {bar,foo}
2 | {baz,bar,foo}