选择标记为标记列表的所有行

时间:2016-02-28 18:03:10

标签: postgresql subset

我想出了这个查询,找到所有标记了某个标记列表的人:

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);

现在我想要,例如标有foobar的所有人。那个例子就是id为2的人。

1 个答案:

答案 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}