6

以下查询返回我们附近的场地(纬度:62.0,经度: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))

是否可以(并且建议)重新使用结果,earth_distance(ll_to_earth(62.0, 25.0), ll_to_earth(lat, lon))而不是为 SELECT、WHERE 和 ORDER BY 子句单独计算结果?

4

3 回答 3

4

GROUP BYand子句中,您可以引用列别名(输出列)甚至是列表项ORDER 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;

如果您想知道将计算打包到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;

就像@Mike 评论的那样,通过声明一个函数STABLE(或IMMUTABLE),您可以通知查询计划器,函数调用的结果可以在单个语句中多次重复用于相同的调用。我在这里引用手册

STABLE 函数不能修改数据库,并保证在给定单个语句中所有行的相同参数的情况下返回相同的结果。此类别允许优化器将函数的多次调用优化为单个调用

大胆强调我的。

于 2012-12-28T21:23:36.907 回答
3

虽然我主要使用 MS SQL Server,但我很确定 PostgreSQL 支持 CTE。尝试类似:

WITH CTE_venues AS (
SELECT *, earth_distance(ll_to_earth(62.0, 25.0), ll_to_earth(lat, lon)) AS distance 
FROM venues 
)
SELECT *
FROM CTE_venues 
WHERE distance <= radius 
ORDER BY distance
于 2012-12-28T19:23:49.877 回答
0

您还可以创建独立或打包函数并在查询中使用它:

 SELECT *
   FROM ...
  WHERE distance <= your_function()  -- OR your_package_name.your_function()
 ORDER BY ...

您可以在选择中使用您的功能:

Select your_function() 
  From your_table...
 Where  ...
于 2012-12-28T20:51:06.933 回答