在PostgreSQL数据库中,有两个具有多对多关系的实体:songs
具有多对多artists
。 artists_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
;
答案 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;