【问题标题】:Order by joined field with many-to-many relation按具有多对多关系的连接字段排序
【发布时间】:2020-04-09 13:24:15
【问题描述】:

在 PostgreSQL 数据库中,有两个实体具有多对多关系:songs 具有多对多 artists。 artists_songs 表用于关系。我想选择歌曲并按第一位艺术家对它们进行排序(按字母顺序排序)。目前 PG 不允许我在不指定 group by 的所有字段的情况下这样做。是否可以仅按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
    ;

【问题讨论】:

  • 不要 GROUP BY 列作为设置函数的参数,例如艺术家姓名。

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


【解决方案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】:

    使用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
    

    【讨论】:

    • 我认为窗口函数是这里最好的答案。所以第一个版本已经足够好了。我没有提到,但查询将有更多的连接,看起来更复杂。无论如何,谢谢,您的回答被接受了!
    • 还有领先的order by s.id会打乱排序,艺人名更有分量。
    • @ka8725 。 . .为什么你认为窗口函数会更好?在 Postgres 中,distinct on 通常性能最好。
    【解决方案3】:

    到目前为止,我提出的最佳解决方案是使用 @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;
    

    【讨论】:

    • 当一首歌曲有多个艺术家时,此解决方案将复制行。我不确定这是你想要的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-05
    • 1970-01-01
    • 2020-11-16
    • 2012-08-30
    • 2011-08-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多