简体   繁体   English

按连接列排序,但在另一列上使用distinct

[英]Order by join column but use distinct on another

I'm building a system in which there are the following tables: 我正在构建一个系统,其中包含以下表格:

  • Song 歌曲
  • Broadcast 广播
  • Station
  • Follow 跟随
  • User 用户

A user follows stations, which have songs on them through broadcasts. 用户跟随通过广播在其上具有歌曲的电台。

I'm building a "feed" of songs for a user based on the stations they follow. 我正在为用户根据他们关注的电台构建歌曲的“馈送”。

Here's the query: 这是查询:

SELECT DISTINCT ON ("broadcasts"."created_at", "songs"."id") songs.*
FROM "songs"
INNER JOIN "broadcasts" ON "songs"."shared_id" = "broadcasts"."song_id"
INNER JOIN "stations" ON "broadcasts"."station_id" = "stations"."id"
INNER JOIN "follows" ON "stations"."id" = "follows"."station_id"
WHERE "follows"."user_id" = 2
ORDER BY broadcasts.created_at desc
LIMIT 18

sql在连接时不能正常工作

Note: shared_id is the same as id. 注意:shared_id与id相同。

As you can see I'm getting duplicate results, which I don't want. 正如你所看到的,我得到了重复的结果,这是我不想要的。 I found out from a previous question that this was due to selecting distinct on broadcasts.created_at. 我从之前的一个问题中发现,这是因为在broadcasts.created_at上选择了distinct。

My question is: How do I modify this query so it will return only unique songs based on their id but still order by broadcasts.created_at ? 我的问题是:如何修改此查询,以便它只返回基于其ID的唯一歌曲, 但仍然通过broadcasts.created_at命令

Try this solution: 尝试此解决方案:

SELECT a.maxcreated, b.*
FROM
    (
        SELECT bb.song_id, MAX(bb.created_at) AS maxcreated
        FROM follows aa
        INNER JOIN broadcasts bb ON aa.station_id = bb.station_id
        WHERE aa.user_id = 2
        GROUP BY bb.song_id
    ) a
INNER JOIN songs b ON a.song_id = b.id
ORDER BY a.maxcreated DESC
LIMIT 18

The FROM subselect retrieves distinct song_id s that are broadcasted by all stations the user follows; FROM选择检索由用户遵循的所有站广播的不同song_id ; it also gets the latest broadcast date associated with each song. 它还获得与每首歌曲相关的最新广播日期。 We have to encase this in a subquery because we have to GROUP BY on the columns we're selecting from, and we only want the unique song_id and the maxdate regardless of the station. 我们必须在子查询中包含它,因为我们必须在我们选择的列上使用GROUP BY ,并且我们只需要唯一的song_id和maxdate而不管站点。

We then join that result in the outer query to the songs table to get the song information associated with each unique song_id 然后,我们将该结果加入到songs表的外部查询中,以获得与每个唯一的song_id相关联的歌曲信息

You can use Common Table Expressions (CTE) if you want a cleaner query (nested queries make things harder to read) 如果想要更清晰的查询,可以使用公用表表达式(CTE) (嵌套查询使得更难以阅读)

I would look like this: 我看起来像这样:

WITH a as (
        SELECT bb.song_id, MAX(bb.created_at) AS maxcreated
        FROM follows aa
        INNER JOIN broadcasts bb ON aa.station_id = bb.station_id
        INNER JOIN songs cc ON bb.song_id = cc.shared_id
        WHERE aa.user_id = 2
        GROUP BY bb.song_id
    )
SELECT
    a.maxcreated,
    b.*
FROM a INNER JOIN
    songs b ON a.song_id = b.id
ORDER BY
    a.maxcreated DESC
LIMIT 18

Using a CTE offers the advantages of improved readability and ease in maintenance of complex queries. 使用CTE具有提高可读性和易于维护复杂查询的优点。 The query can be divided into separate, simple, logical building blocks. 查询可以分为单独的简单逻辑构建块。 These simple blocks can then be used to build more complex, interim CTEs until the final result set is generated. 然后,可以使用这些简单的块来构建更复杂的临时CTE,直到生成最终结果集。

尝试添加GROUP BY Songs.id

I had a very similar query I was doing between listens , tracks and albums and it took me a long while to figure it out (hours). 我在listenstracksalbums之间做了一个非常相似的查询,我花了很长时间来弄明白(小时)。

If you use a GROUP_BY songs.id , you can get it to work by ordering by MAX(broadcasts.created_at) DESC . 如果您使用GROUP_BY songs.id ,您可以通过MAX(broadcasts.created_at) DESC订购来使其工作。

Here's what the full SQL looks like: 这是完整的SQL的样子:

SELECT songs.* FROM "songs"
INNER JOIN "broadcasts" ON "songs"."shared_id" = "broadcasts"."song_id"
INNER JOIN "stations" ON "broadcasts"."station_id" = "stations"."id"
INNER JOIN "follows" ON "stations"."id" = "follows"."station_id"
WHERE "follows"."user_id" = 2
GROUP BY songs.id
ORDER BY MAX(broadcasts.created_at) desc
LIMIT 18;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM