ran*_*guy 6 sql postgresql select sql-order-by where
以下查询返回我们附近的场地(lat:62.0,lon:25.0),其中我们按照距离排列的半径:
SELECT *,
earth_distance(ll_to_earth(62.0, 25.0),
ll_to_earth(lat, lon)) AS distance
FROM venues
WHERE earth_distance(ll_to_earth(62.0, 25.0), ll_to_earth(lat, lon)) <= radius
ORDER BY earth_distance(ll_to_earth(62.0, 25.0), ll_to_earth(lat, lon))
Run Code Online (Sandbox Code Playgroud)
是否可以(并且建议)重复使用结果earth_distance(ll_to_earth(62.0, 25.0), ll_to_earth(lat, lon))而不是为SELECT,WHERE和ORDER BY子句单独计算结果?
在GROUP BYandORDER BY子句中,您可以引用列别名(输出列)甚至SELECT列表项的序号。我引用了手册ORDER BY:
每个表达式可以是输出列(SELECT 列表项)的名称或序号,也可以是由输入列值形成的任意表达式。
大胆强调我的。
但在WHEREandHAVING子句中,您只能引用基表中的列(输入列),因此您必须拼写出函数调用。
SELECT *, earth_distance(ll_to_earth(62.0, 25.0), ll_to_earth(lat, lon)) AS dist
FROM venues
WHERE earth_distance(ll_to_earth(62.0, 25.0), ll_to_earth(lat, lon)) <= radius
ORDER BY distance;
Run Code Online (Sandbox Code Playgroud)
如果您想知道将计算打包到CTE或子查询中是否更快,只需使用 进行测试即可EXPLAIN ANALYZE。(我对此表示怀疑。)
SELECT *
FROM (
SELECT *
,earth_distance(ll_to_earth(62.0, 25.0), ll_to_earth(lat, lon)) AS dist
FROM venues
) x
WHERE distance <= radius
ORDER BY distance;
Run Code Online (Sandbox Code Playgroud)
就像@Mike 评论的那样,通过声明一个函数STABLE(或IMMUTABLE),您可以通知查询规划器,函数调用的结果可以在单个语句中的相同调用中多次重用。我在这里引用手册:
STABLE 函数无法修改数据库,并且保证在给定单个语句中所有行的相同参数的情况下返回相同的结果。该类别允许优化器将函数的多个调用优化为单个调用。
大胆强调我的。