我使用 PostgreSQL 9.1(我们的托管平台升级后立即使用 9.2)进行此查询:
SELECT
media_files.album,
media_files.artist,
ARRAY_AGG (media_files. ID) AS media_file_ids
FROM
media_files
INNER JOIN playlist_media_files ON media_files.id = playlist_media_files.media_file_id
WHERE
playlist_media_files.playlist_id = 1
GROUP BY
media_files.album,
media_files.artist
ORDER BY
media_files.album ASC
它工作正常,目标是提取专辑/艺术家组合,并在结果集中为该特定组合提供一系列媒体文件 ID。
问题是我在媒体文件中有另一列,它是
artwork
.artwork
对于每个媒体文件(即使在同一个专辑中)都是唯一的,但在结果集中我只需要返回集合中的第一个。因此,对于包含 10 个媒体文件的专辑,我也有 10 个相应的艺术品,但我只想返回第一个(或为该集合随机挑选的一个)。
是否可以仅使用 SQL/窗口函数(first_value 超过 ..)?
最佳答案
是的,这是可能的。首先,让我们通过添加别名和显式列限定符来调整您的查询,以便清楚什么来自哪里 - 假设我猜对了,因为没有表定义我无法确定:
SELECT
mf.album,
mf.artist,
ARRAY_AGG (mf.id) AS media_file_ids
FROM
"media_files" mf
INNER JOIN "playlist_media_files" pmf ON mf.id = pmf.media_file_id
WHERE
pmf.playlist_id = 1
GROUP BY
mf.album,
mf.artist
ORDER BY
mf.album ASC
现在您可以在
SELECT
中使用子查询列出或使用 DISTINCT ON
,虽然它看起来像任何基于 DISTINCT ON
的解决方案会如此复杂以至于不值得。你真正想要的是类似
pick_arbitrary_value_agg
的东西聚合只是选择它看到的第一个值并将其余的扔掉。没有这样的聚合,并且它真的不值得为工作而实现。您可以使用 min(artwork)
或 max(artwork)
您可能会发现这实际上比后面的解决方案性能更好。要使用子查询,请留下
ORDER BY
按原样添加以下内容作为您的 SELECT
中的额外列列表:(SELECT mf2.artwork
FROM media_files mf2
WHERE mf2.artist = mf.artist
AND mf2.album = mf.album
LIMIT 1) AS picked_artwork
您可以通过添加
ORDER BY random()
以牺牲性能为代价随机化选定的艺术品。之前LIMIT 1
以上。或者,这里有一种快速而肮脏的方式来实现内联随机行的选择:
(array_agg(artwork))[width_bucket(random(),0,1,count(artwork)::integer)]
由于没有样本数据,我无法测试这些修改。让我知道是否有问题。
关于sql - 选择 group by 中的第一行或随机行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13853569/