以下查询返回我们附近的场地(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))
是否可以(并且建议)重用earth_distance(ll_to_earth(62.0, 25.0), ll_to_earth(lat, lon))
的结果,而不是单独为SELECT,WHERE和ORDER BY子句计算它?
答案 0 :(得分:4)
在GROUP BY
和ORDER BY
子句中,您可以引用列别名(输出列)或偶数SELECT
列表项的序号。我引用the manual on ORDER BY
:
每个表达式可以是输出列的名称或序号 (SELECT list item),或者它可以是由...形成的任意表达式 输入列值。
大胆强调我的。
但是在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 commented类似,通过声明函数STABLE
(或IMMUTABLE
),您可以通知查询计划程序,对于单个语句中的相同调用,函数调用的结果可以重复使用多次。我引用the manual here:
STABLE函数无法修改数据库并且可以保证 给出a中所有行的相同参数,返回相同的结果 单一陈述。此类别允许优化程序进行优化 多次调用该函数进行一次调用。
大胆强调我的。
答案 1 :(得分: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
答案 2 :(得分:0)
您还可以创建独立或打包功能,并在查询中使用它:
SELECT *
FROM ...
WHERE distance <= your_function() -- OR your_package_name.your_function()
ORDER BY ...
您可以在选择中使用您的功能:
Select your_function()
From your_table...
Where ...