如何获得每个产品的最新文档?

时间:2019-07-15 09:56:41

标签: sql postgresql group-by greatest-n-per-group

我有以下简化表:

Product: [uniqueId|name]
ProductAttachment: [FK productId|FK attachmentId]
Attachment: [uniqueId|createdOn|name]

产品表和附件表具有n:m关系,其中productAttachment是中间表。 不能保证每个附件的createdOn都是唯一的。

我正在尝试获取每种产品的最新附件。 我可以加入表格,但是我不知道如何在不获得每个产品多个行的情况下获得每个产品的完整附件行。这是一个更大的查询的一部分,因此理想情况下,我希望这样做而不必更改其余的查询。如果我可以从子查询中获取attachmentId,则可以在单独的联接中使用它。

我看过一些类似的问题,例如:

SQL select only rows with max value on a column

Finding the most recent timestamp per event

但据我所知,对于n:m关系,这些答案不起作用。 我尝试使用聚合子查询,但仅获得附件的创建日期,如果将附件ID添加到GROUP BY子句,则每个产品将获得多个附件。

SELECT p.UniqueId, mostRecentAttachment.created
  FROM ps.product AS p
       LEFT JOIN (SELECT pa.productId, MAX(a.created) AS created
                     FROM ps.productAttachment AS pa
                          INNER JOIN bs.attachment AS a ON pa.attachmentId = a.uniqueId
                    GROUP BY pa.productId) AS mostRecentAttachment ON mostRecentAttachment.productId = p.uniqueId
 WHERE p.active

我希望每个产品一行(大约有12000个产品),如果产品有一个,则是最近的附件。

1 个答案:

答案 0 :(得分:1)

demo:db<>fiddle

使用DISTINCT ON仅允许过滤有序组的第一个元素。这里的组是产品。加入附件后,您可以按其日期降序排列它们的附件。因此,在每个产品组中,最新的附件成为第一。该记录由DISTINCT ON子句获取。

SELECT DISTINCT ON (p.unique_id)
    p.*,
    a.*
FROM
    products p 
JOIN product_attachment pa ON p.unique_id = pa.product_id
JOIN attachments a ON pa.attachment_id = a.unique_id
ORDER BY p.unique_id, a.created_on DESC