我有一张叫做"地方"的桌子
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?
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/