如何重用SELECT,WHERE和ORDER BY子句的结果?

时间:2012-12-28 19:16:21

标签: 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))

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

3 个答案:

答案 0 :(得分:4)

GROUP BYORDER BY子句中,您可以引用列别名(输出列)或偶数SELECT列表项的序号。我引用the manual on ORDER BY

  

每个表达式可以是输出列的名称或序号   (SELECT list item),或者它可以是由...形成的任意表达式   输入列值。

大胆强调我的。

但是在WHEREHAVING子句中,您只能引用基表(输入列)中的列,因此您必须拼出函数调用。

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  ...