首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >具有不同ORDER BY的PostgreSQL DISTINCT ON

具有不同ORDER BY的PostgreSQL DISTINCT ON
EN

Stack Overflow用户
提问于 2012-03-21 05:59:37
回答 7查看 244K关注 0票数 267

我想运行这个查询:

代码语言:javascript
复制
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排序

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2012-03-21 06:08:32

文档中写道:

表达式DISTINCT ON (

,... )只保留给定表达式求值为相等的每组行中的第一行。..。请注意,除非使用ORDER BY来确保所需的行先出现,否则每个集合的“第一行”是不可预测的。..。DISTINCT ON表达式必须与最左侧的ORDER BY表达式匹配。

Official documentation

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

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

应该在大多数DBMS中工作的一般解决方案:

代码语言:javascript
复制
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

一个更加面向PostgreSQL的解决方案,基于@hkf的回答:

代码语言:javascript
复制
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

问题在这里得到澄清、扩展和解决:Selecting rows ordered by some column and distinct on another

票数 265
EN

Stack Overflow用户

发布于 2012-03-21 06:04:34

可以在子查询中按address_id排序,然后在外部查询中按所需排序。

代码语言:javascript
复制
SELECT * FROM 
    (SELECT DISTINCT ON (address_id) purchases.address_id, purchases.* 
    FROM "purchases" 
    WHERE "purchases"."product_id" = 1 ORDER BY address_id DESC ) 
ORDER BY purchased_at DESC
票数 68
EN

Stack Overflow用户

发布于 2012-03-21 06:40:27

子查询可以解决这个问题:

代码语言:javascript
复制
SELECT *
FROM  (
    SELECT DISTINCT ON (address_id) *
    FROM   purchases
    WHERE  product_id = 1
    ) p
ORDER  BY purchased_at DESC;

ORDER BY中的前导表达式必须与DISTINCT ON中的列一致,因此不能按同一SELECT中的不同列排序。

如果要从每个集合中选取特定行,则仅在子查询中使用额外的ORDER BY

代码语言:javascript
复制
SELECT *
FROM  (
    SELECT DISTINCT ON (address_id) *
    FROM   purchases
    WHERE  product_id = 1
    ORDER  BY address_id, purchased_at DESC  -- get "latest" row per address_id
    ) p
ORDER  BY purchased_at DESC;

如果purchased_at可以为NULL,则使用DESC NULLS LAST -并匹配您的索引以获得最佳性能。请参见:

相关的,有更多解释:

票数 66
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9795660

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档