Postgresql 选择按某列排序并在另一列上不同的行

Postgresql 选择按某列排序并在另一列上不同的行,postgresql,greatest-n-per-group,distinct-on,Postgresql,Greatest N Per Group,Distinct On,有关— 我有表购买产品id、购买地点、地址id 样本数据: | id | product_id | purchased_at | address_id | | 1 | 2 | 20 Mar 2012 21:01 | 1 | | 2 | 2 | 20 Mar 2012 21:33 | 1 | | 3 | 2 | 20 Mar 2012 21:39 | 2 | | 4 |

有关—

我有表购买产品id、购买地点、地址id

样本数据:

| id | product_id |   purchased_at    | address_id |
| 1  |     2      | 20 Mar 2012 21:01 |     1      |
| 2  |     2      | 20 Mar 2012 21:33 |     1      |
| 3  |     2      | 20 Mar 2012 21:39 |     2      |
| 4  |     2      | 20 Mar 2012 21:48 |     2      |
我期望的结果是每个地址\u id的最新购买的产品整行,并且该结果必须按“购买的\u at”字段的子代顺序排序:

| id | product_id |   purchased_at    | address_id |
| 4  |     2      | 20 Mar 2012 21:48 |     2      |
| 2  |     2      | 20 Mar 2012 21:33 |     1      |
使用查询:

SELECT DISTINCT ON (address_id) purchases.address_id, purchases.*
FROM "purchases"
WHERE "purchases"."product_id" = 2
ORDER BY purchases.address_id ASC, purchases.purchased_at DESC
我得到:

| id | product_id |   purchased_at    | address_id |
| 2  |     2      | 20 Mar 2012 21:33 |     1      |
| 4  |     2      | 20 Mar 2012 21:48 |     2      |

因此,行是相同的,但顺序是错误的。有办法解决吗?

这是一个很清楚的问题:

SELECT t1.* FROM purchases t1
LEFT JOIN purchases t2
ON t1.address_id = t2.address_id AND t1.purchased_at < t2.purchased_at
WHERE t2.purchased_at IS NULL
ORDER BY t1.purchased_at DESC
您的订单由用于为每个不同的地址id选择要生成的行。然后,如果要对结果记录进行排序,请在子选择上进行DISTINCT并对其结果进行排序:

SELECT * FROM
(
  SELECT DISTINCT ON (address_id) purchases.address_id, purchases.*
  FROM "purchases"
  WHERE "purchases"."product_id" = 2
  ORDER BY purchases.address_id ASC, purchases.purchased_at DESC
) distinct_addrs
order by distinct_addrs.purchased_at DESC

这个查询比看起来更难正确地重新措辞

无法正确处理两个候选行具有相同给定值的情况:它将返回两行

您可以通过以下方式获得正确的行为:

SELECT * FROM purchases AS given
WHERE product_id = 2
AND NOT EXISTS (
    SELECT NULL FROM purchases AS other
    WHERE given.address_id = other.address_id
    AND (given.purchased_at < other.purchased_at OR given.id < other.id)
)
ORDER BY purchased_at DESC
请注意,它有一个比较id值的后备方法,以消除购买的_at值匹配的情况的歧义。这确保了该条件仅适用于具有相同地址id值的行中的一行

使用DISTINCT ON的原始查询会自动处理此情况

还请注意,您必须在给定的.purchased_at
通过使用DISTINCT ON和外部子查询,可以更容易地正确、易懂地编写此查询。

用很短的话来说就是这样的建议:现在,唯一购买的价值没有更大价值的是max,只返回那些行:为了进一步阅读,看看这种查询方法的效率如何?qq关于你的第一种方法:如果最后两次购买是同时进行的呢?看起来同一个地址有两行。这不是公认的答案。不适用于重复购买的记录。不,他正在寻找根据问题返回的单个记录。如果购买的_at与另一个记录相同,那么这个解决方案实际上并不能解决它,而像我这样来这里寻找同一问题解决方案的任何人通常都会将公认的答案视为理想的方法,但在这种情况下,它是完全不正确的。最好是重复而不是重复。tho:只是更正确的问题。在上一篇文章中,我得到了明确的答案-不:谢谢你的回答,但我认为join会比subquery更好,特别是当你想在rails内部使用它时,不仅仅是查询执行,而是以某种rails方式构建它。最佳答案帮助我理解:这实际上是唯一一个好的工作答案。此外,您也可以在第二个SELECT行中使用SELECT DISTINCT ON address_id*。如果我想将其限制为对购买的_进行分页,那么最终会出现问题,必须在外部应用该限制。但这意味着我们总是在应用限制之前获取所有行。
SELECT * FROM purchases AS given
WHERE product_id = 2
AND NOT EXISTS (
    SELECT NULL FROM purchases AS other
    WHERE given.address_id = other.address_id
    AND (given.purchased_at < other.purchased_at OR given.id < other.id)
)
ORDER BY purchased_at DESC