select 用标签列表标记的所有行
select all rows tagged with a list of tags
我想出了这个查询来查找所有标记有特定标签列表的人:
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)
不知怎的,我觉得我把事情搞得太复杂了。现在我们没有足够的数据来证明它的表现不佳,但真的没有更好的方法吗?
编辑: 最小 table 定义:
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 的人。
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}
我想出了这个查询来查找所有标记有特定标签列表的人:
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)
不知怎的,我觉得我把事情搞得太复杂了。现在我们没有足够的数据来证明它的表现不佳,但真的没有更好的方法吗?
编辑: 最小 table 定义:
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 的人。
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}