1

我正在构建一个系统,其中有以下表格:

  • 歌曲
  • 播送
  • 车站
  • 跟随
  • 用户

用户关注电台,这些电台通过广播播放歌曲。

我正在根据用户关注的电台为用户构建歌曲“提要”。

这是查询:

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在加入时无法正常工作

注意:shared_id 与 id 相同。

如您所见,我得到了重复的结果,这是我不想要的。我从上一个问题中发现,这是由于在 broadcasts.created_at 上选择了 distinct。

我的问题是:如何修改此查询,使其仅根据其 id 返回唯一歌曲,但仍按 broadcasts.created_at 排序

4

4 回答 4

2

如果您想要更清晰的查询(嵌套查询使事情更难阅读),您可以使用公用表表达式 (CTE )

我看起来像这样:

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

使用 CTE 具有提高可读性和易于维护复杂查询的优点。查询可以分为单独的、简单的、逻辑的构建块。然后可以使用这些简单的块来构建更复杂的临时 CTE,直到生成最终结果集。

于 2012-07-07T02:57:04.683 回答
2

试试这个解决方案:

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

FROM子选择检索song_id用户关注的所有电台广播的不同 s ;它还获取与每首歌曲相关的最新广播日期。我们必须将它封装在子查询中,因为我们必须GROUP BY在我们从中选择的列上,并且我们只想要唯一song_id和 maxdate 而不管站。

然后,我们将外部查询中的结果连接到songs表中,以获取与每个唯一相关联的歌曲信息song_id

于 2012-07-07T02:35:41.803 回答
0

尝试添加GROUP BY Songs.id

于 2012-07-07T02:01:27.783 回答
0

我在 之间有一个非常相似的查询listens,我花了很长时间才弄清楚(几个小时)。tracksalbums

如果您使用 a GROUP_BY songs.id,您可以通过 order by 使其工作MAX(broadcasts.created_at) DESC

完整的 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;
于 2014-07-06T11:17:00.097 回答