PostgreSQL - 获取聚合列的相关列

Dav*_*eto 0 sql postgresql

我有一张叫做"地方"的桌子

origin | destiny | distance
---------------------------
A      | X       | 5
A      | Y       | 8
B      | X       | 12
B      | Y       | 9
Run Code Online (Sandbox Code Playgroud)

对于每个起源,我想找出哪个是最接近的命运.在MySQL中我能做到

SELECT origin, destiny, MIN(distance) FROM places GROUP BY origin
Run Code Online (Sandbox Code Playgroud)

我可以期待以下结果

origin | destiny | distance
---------------------------
A      | X       | 5
B      | y       | 9
Run Code Online (Sandbox Code Playgroud)

不幸的是,这个查询在PostgreSQL中不起作用.Postgre强迫我把"命运"放在他自己的聚合函数中,或者将它定义为GROUP BY语句的另一个参数.两种"解决方案"完全改变了我想要的结果.

我怎么能将上面的MySQL查询翻译成PostgreSQL?

a_h*_*ame 5

MySQL是唯一允许通过处理破解(在MySQL术语中"丢失")组的DBMS.每个其他DBMS(包括Postgres)都会拒绝您的原始声明.

在Postgres中,您可以使用distinct on运算符来实现相同的功能:

select distinct on (origin) 
       origin, 
       destiny, 
       distance
from places
order by origin, distance;
Run Code Online (Sandbox Code Playgroud)

ANSI解决方案将是这样的:

select p.origin, 
       p.destiny, 
       p.distance
from places p
  join (select p2.origin, min(p2.distance) as distance
        from places  p2
        group by origin
) t on t.origin = p.origin and t.distance = p.distance
order by origin;
Run Code Online (Sandbox Code Playgroud)

或者没有使用窗口函数的连接

select t.origin,
       t.destiny,
       t.distance
from (
    select origin, 
           destiny, 
           distance, 
           min(distance) over (partition by origin) as min_dist
    from places
) t 
where distance = min_dist
order by origin;
Run Code Online (Sandbox Code Playgroud)

或者具有窗口函数的另一种解

select distinct origin,
       first_value(destiny) over (partition by origin order by distance) as destiny, 
       min(distance) over (partition by origin) as distance
from places
order by origin;
Run Code Online (Sandbox Code Playgroud)

我的猜测是第一个(Postgres具体)可能是最快的一个.

这是所有三种解决方案的SQLFiddle:http://sqlfiddle.com/#!12/68308/2


请注意,MySQL结果可能实际上是错误的,因为它将为命运返回任意(=随机)值.MySQL返回的值可能不是属于最低距离的值.

有关在MySQL中处理的损坏组的更多详细信息,请访问:http://www.mysqlperformanceblog.com/2006/09/06/wrong-group-by-makes-your-queries-fragile/