通过具有多对多关系的联合字段进行排序

时间:2020-04-09 13:24:15

标签: sql postgresql join group-by sql-order-by

在PostgreSQL数据库中,有两个具有多对多关系的实体:songs具有多对多artistsartists_songs表用于该关系。我想选择歌曲,然后按第一位艺术家的顺序对其进行排序(按字母顺序排序)。当前,PG不允许我在不指定分组依据中的所有字段的情况下进行操作。是否可以仅按songs.id进行分组的歌曲选择和排序?

这是我的SQL查询:

select ss.*
  from (
    select songs.*, min(artists.name) as artist_name
    from songs
      left join artists_songs on artists_songs.song_id = songs.id
      left join artists on artists.id = artists_songs.artist_id
      group by songs.id, artists.name
    ) ss
    group by ss.id
    order by ss.artist_name
    ;

3 个答案:

答案 0 :(得分:1)

使用distinct on

select distinct on (s.id) s.*, sa.name as artist_name
from songs s left join
     artists_songs ars
     on ars.song_id = s.id left join
     artists a
     on a.id = ars.artist_id    
order by s.id, sa.name;

如果要进行特殊排序,可以使用子查询:

select s.*
from (select distinct on (s.id) s.*, sa.name as artist_name
      from songs s left join
           artists_songs ars
           on ars.song_id = s.id left join
           artists a
           on a.id = ars.artist_id    
      order by s.id, sa.name
     ) s
order by artist_name

答案 1 :(得分:1)

这看起来像是横向连接的好地方:

select s.*, a.name
from songs s
cross join lateral (
    select a.name
    from artists_songs ars
    inner join artists a on a.id = ars.artist_id
    where ars.song_id = s.id
    order by a.name
    limit 1
) a
order by a.name

答案 2 :(得分:0)

到目前为止,我提出的最佳解决方案是使用@ gordon-linoff最初声明的窗口函数:

select s.id, min(a.name) over (partition by s.id) as artist_name
from songs s left join
    artists_songs ars
    on ars.song_id = s.id left join
    artists a
    on a.id = ars.artist_id
order by artist_name;