6

次のクエリは、半径が距離順に分類されている、近くの会場(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句に対して個別に計算する代わりに、からの結果を再利用することは可能(および推奨)ですか?

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 に答える