2016-02-28 165 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