具有不同 ORDER BY 的 PostgreSQL DISTINCT ON

新手上路,请多包涵

我想运行这个查询:

 SELECT DISTINCT ON (address_id) purchases.address_id, purchases.*
FROM purchases
WHERE purchases.product_id = 1
ORDER BY purchases.purchased_at DESC

但我得到这个错误:

PG::Error: ERROR: SELECT DISTINCT ON 表达式必须匹配初始 ORDER BY 表达式

添加 address_id 作为第一个 ORDER BY 表达式可以消除错误,但我真的不想在 address_id 上添加排序。是否可以不按 address_id 订购?

原文由 sl_bug 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 481
2 个回答

文档说:

DISTINCT ON ( 表达式 [, …] ) 仅保留给定表达式计算结果为相等的每组行的第一行。 […] 请注意,除非使用 ORDER BY 来确保所需的行首先出现,否则每组的“第一行”是不可预测的。 […] DISTINCT ON 表达式必须匹配最左边的 ORDER BY 表达式。

官方文档

因此,您必须将 address_id 添加到 order by。

或者,如果您正在寻找包含每个 address_id 的最新购买产品的完整行,并且该结果按 purchased_at 排序,那么您正在尝试解决最大的 N per可以通过以下方法解决的组问题:

适用于大多数 DBMS 的通用解决方案:

 SELECT t1.* FROM purchases t1
JOIN (
    SELECT address_id, max(purchased_at) max_purchased_at
    FROM purchases
    WHERE product_id = 1
    GROUP BY address_id
) t2
ON t1.address_id = t2.address_id AND t1.purchased_at = t2.max_purchased_at
ORDER BY t1.purchased_at DESC

基于@hkf 的答案的更面向 PostgreSQL 的解决方案:

 SELECT * FROM (
  SELECT DISTINCT ON (address_id) *
  FROM purchases
  WHERE product_id = 1
  ORDER BY address_id, purchased_at DESC
) t
ORDER BY purchased_at DESC

问题在这里得到了澄清、扩展和解决: 选择按某列排序的行和另一列不同的行

原文由 Mosty Mostacho 发布,翻译遵循 CC BY-SA 3.0 许可协议

试试这个查询。

 SELECT DISTINCT ON (address_id) *
FROM   purchases
WHERE  product_id = 1
ORDER  BY address_id, purchased_at DESC

原文由 Subhan Ahmed 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进