[英]Order by join column but use distinct on another
I'm building a system in which there are the following tables: 我正在构建一个系统,其中包含以下表格:
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
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). 我在
listens
, tracks
和albums
之间做了一个非常相似的查询,我花了很长时间来弄明白(小时)。
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.