微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Postgresql 9.3 – array_agg challenge

我正在尝试理解 Postgresql 9.3中的array_agg函数.我为每个可能有兴趣参与的人提供了一个有趣的例子.

20世纪80年代的任何一部美国电影迷都可能熟悉一起出现在很多热门影片中的“小伙子”.在wikipedia上使用关于brat pack影片的信息,我创建了表格,当它们连接在一起时,可以告诉我们谁在彼此工作 – 如果我们有正确的查询

/*
See:  http://en.wikipedia.org/wiki/Brat_Pack_(actors)
*/

CREATE TABLE actor(
    id SERIAL PRIMARY KEY,name VARCHAR(50)
);
insert into actor(name) values ('Emilio Estevez'),('Anthony Michael Hall'),('Rob Lowe'),('Andrew McCarthy'),('Demi Moore'),('Judd Nelson'),('Molly Ringwald'),('Ally Sheedy')

CREATE TABLE movie(
    id SERIAL PRIMARY KEY,title VARCHAR(200)
);
insert into movie(title) values ('The Outsiders'),('Class'),('Sixteen Candles'),('Oxford Blues'),('The Breakfast Club'),('St. Elmos Fire'),('Pretty in Pink'),('Blue City'),('About Last Night'),('Wisdom'),('Fresh Horses'),('Betsys Wedding'),('Hail Caesar');

CREATE TABLE movie_brats(
    id SERIAL PRIMARY KEY,movie_id INT REFERENCES movie(id),actor_id INT REFERENCES actor(id)
);
insert into movie_brats(movie_id,actor_id) values (1,1),(1,3),(2,4),(3,2),7),(4,8),(5,6),(6,5),(7,(8,(9,(10,(11,(12,(13,6);

查询显示brat包的每个成员使用的不同列表,在两列中按名称排序

Name                      Worked With
 ----------------------------------------------------------------------------------------------------------------
Emelio Estevez       |  Emilio Estevez,Anthony Michael Hall,Rob Lowe,Andrew McCarthy,Demi Moore,Judd Nelson,Molly Ringwald,Ally Sheedy
*/

我破碎的查询

select a1.name,array_to_string(array_agg(a2.name),',') as Co_Stars
from actor a1,actor a2,movie m,movie_brats mb
where 
    m.id = mb.movie_id
    and a1.id = mb.actor_id
    and a2.id = mb.actor_id
group by a1.id

解决方法

SQL Fiddle

with v as (
    select
        a.id as actor_id,a.name as actor_name,m.id as m_id
    from
        actor a
        inner join
        movie_brats mb on a.id = mb.actor_id
        inner join
        movie m on m.id = mb.movie_id
)
select
    v1.actor_name as "Name",string_agg(
        distinct v2.actor_name,' order by v2.actor_name
    ) as "Worked With"
from
    v v1
    left join
    v v2 on v1.m_id = v2.m_id and v1.actor_id != v2.actor_id
group by 1
order by 1

如果它们在多个电影中一起工作,则上面的不同聚合对于不显示重复的名称是必要的.

左连接是必要的,不能抑制不与列表中任何其他人一起工作的actor,就像内连接一样.

如果你想展示他们合作的电影:SQL Fiddle

with v as (
    select
        a.id as actor_id,m.id as m_id,m.title as title
    from
        actor a
        inner join
        movie_brats mb on a.id = mb.actor_id
        inner join
        movie m on m.id = mb.movie_id
)
select
    a1 as "Name",string_agg(
        format('%s (in %s)',a2,title),'
        order by format('%s (in %s)',title)
    ) as "Worked With"
from (
    select 
        v1.actor_name as a1,v2.actor_name as a2,string_agg(v1.title,' order by v1.title) as title    
    from
        v v1
        left join
        v v2 on v1.m_id = v2.m_id and v1.actor_id != v2.actor_id
    group by 1,2
) s
group by 1
order by 1

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐