PostgreSQL使用不同的ORDER BY打开 [英] PostgreSQL DISTINCT ON with different ORDER BY
问题描述
我要运行此查询:
SELECT DISTINCT ON (address_id) purchases.address_id, purchases.*
FROM purchases
WHERE purchases.product_id = 1
ORDER BY purchases.purchased_at DESC
但是我得到这个错误:
PG ::错误:错误: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
这篇关于PostgreSQL使用不同的ORDER BY打开的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!