Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何重用SELECT、WHERE和ORDER BY子句的结果?_Sql_Postgresql_Select_Sql Order By_Where - Fatal编程技术网

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

Sql 如何重用SELECT、WHERE和ORDER BY子句的结果?,sql,postgresql,select,sql-order-by,where,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_

以下查询返回我们附近的场地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\u distancell\u to\u earth62.0、25.0、ll\u to\u EarthAt、lon的结果,而不是单独计算SELECT、WHERE和ORDER BY子句?

虽然我主要使用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 ...
在GROUP BY和ORDER BY子句中,可以引用列别名、输出列,甚至是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;
与此类似,通过声明函数稳定或不可变,您可以通知查询计划器,函数调用的结果可以在单个语句中重复使用多次。我引述:

稳定的函数不能修改数据库,并保证 如果给定同一行中所有行的相同参数,则返回相同的结果 单一声明。此类别允许优化器进行优化 将函数的多个调用转换为单个调用


粗体强调我的。

我认为如果函数标记为,结果将被重复使用。如果我错了,希望博士后专家能纠正我。@MikeChristensen:是的,这就是它通常的工作原理。即使是稳定的也足够了,因为它在一条语句中声明了result常量。即使在事务之间,也需要使用IMMUTABLE来断言常量结果。这是一个函数在索引中可用所必需的,例如,完全无用的答案。1计算的距离仍需要在select子句中,即select*不起作用。2结果集仍然必须按函数结果排序。3这相当于一个查询,与最初发布的内容完全相同。问题是关于函数的波动性,以及查询优化器是对函数求值三次还是一次。。。请再看一次我的例子-函数可以在选择中使用。。。仅供参考。。。问题是如何重用结果。函数返回一个结果,可以重用…很好的答案。需要明确的是:您怀疑子查询将比CTE快,或者怀疑使用CTE/子查询而不是仅仅计算两次是否值得?@randomguy:我希望普通形式比使用子查询或CTE都快。但只要测试一下就知道了。测试>>猜测。@ErwinBrandstetter:根据我的经验,CTE始终保持不变,即使只引用一次,哪个IMO应该与等效视图或子查询表单等效。因此,它们不会被计划生成器分解和重新组装,这可能导致次优计划。有利的一面是:这将使射程表相对较小,且不相关,这将减少可能计划数量的组合爆炸。我没有试过9.2yet@wildplasser:如果您的观察结果成立,那么CTE对于非常大和复杂的查询的有用性会增加,因为在这些查询中,规划开销开始影响性能。您应该将不会进一步优化的子查询放入CTE中,以降低主查询的复杂性。等我有时间的时候,我得测试一下。
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;
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;