具有不同 ORDER BY 的 PostgreSQL DISTINCT ON [英] PostgreSQL DISTINCT ON with different ORDER BY

查看:19
本文介绍了具有不同 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 表达式

PG::Error: ERROR: SELECT DISTINCT ON expressions must match initial ORDER BY expressions

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

Adding address_id as first ORDER BY expression silences the error, but I really don't want to add sorting over address_id. Is it possible to do without ordering by address_id?

推荐答案

文档说:

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

DISTINCT ON ( expression [, ...] ) keeps only the first row of each set of rows where the given expressions evaluate to equal. [...] Note that the "first row" of each set is unpredictable unless ORDER BY is used to ensure that the desired row appears first. [...] The DISTINCT ON expression(s) must match the leftmost ORDER BY expression(s).

官方文档

因此您必须将 address_id 添加到订单中.

So you'll have to add the address_id to the order by.

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

Alternatively, if you're looking for the full row that contains the most recent purchased product for each address_id and that result sorted by purchased_at then you're trying to solve a greatest N per group problem which can be solved by the following approaches:

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

The general solution that should work in most DBMSs:

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 的解决方案:

A more PostgreSQL-oriented solution based on @hkf's answer:

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

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

Problem clarified, extended and solved here: Selecting rows ordered by some column and distinct on another

这篇关于具有不同 ORDER BY 的 PostgreSQL DISTINCT ON的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆