2016-02-28 162 views
1

列表中的所有行,我想出了这个查询发现,凡标有标签一定列表中的所有的人:选择标记的标签

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的人。

+2

请提供示例数据到此查询中的每个表。 – jkdba

+1

并提供表格定义。这样就不可能回答。 – Patrick

+0

添加了表格定义和示例数据。这是否真的给你*在查询中看不到更多简洁的任何*信息? – panzi

回答

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} 
+0

伟大的,除了':: text []'',我不得不写'::字符变化[]',使其工作。 – panzi