以下查询返回我们附近的场地(纬度: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 子句单独计算?
在
GROUP BY
和 ORDER BY
子句中,您可以引用列别名(输出列),甚至可以引用 SELECT
列表项的序数。 说明书:
每个表达式可以是 输出列的名称或序号 (SELECT 列表项),或者它可以是由以下形式形成的任意表达式 输入列值。
我的粗体强调。
但是在
WHERE
和 HAVING
子句中,您只能引用基表中的列(输入列),因此您必须拼写出您的函数调用。
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
),您可以通知查询规划器,函数调用的结果可以在单个语句中针对相同的调用重复使用多次。 说明书:
函数不能修改数据库,并且保证 给定 a 中所有行的相同参数,返回相同的结果 单一声明。该类别允许优化器进行优化 对函数的多次调用改为一次调用。STABLE
我的粗体强调。
虽然我主要使用 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
您还可以创建独立或打包函数并在查询中使用它:
SELECT *
FROM ...
WHERE distance <= your_function() -- OR your_package_name.your_function()
ORDER BY ...
您可以在选择中使用您的功能:
Select your_function()
From your_table...
Where ...