このクエリは大いに役立つはずです(多く より速い):
WITH school AS (
SELECT s.osm_id AS school_id, text 'school' AS type, s.osm_id, s.name, s.way_geo
FROM planet_osm_point s
, LATERAL (
SELECT 1 FROM planet_osm_point
WHERE ST_DWithin(way_geo, s.way_geo, 500, false)
AND amenity = 'bar'
LIMIT 1 -- bar exists -- most selective first if possible
) b
, LATERAL (
SELECT 1 FROM planet_osm_point
WHERE ST_DWithin(way_geo, s.way_geo, 500, false)
AND amenity = 'restaurant'
LIMIT 1 -- restaurant exists
) r
WHERE s.amenity = 'school'
)
SELECT * FROM (
TABLE school -- schools
UNION ALL -- bars
SELECT s.school_id, 'bar', x.*
FROM school s
, LATERAL (
SELECT osm_id, name, way_geo
FROM planet_osm_point
WHERE ST_DWithin(way_geo, s.way_geo, 500, false)
AND amenity = 'bar'
) x
UNION ALL -- restaurants
SELECT s.school_id, 'rest.', x.*
FROM school s
, LATERAL (
SELECT osm_id, name, way_geo
FROM planet_osm_point
WHERE ST_DWithin(way_geo, s.way_geo, 500, false)
AND amenity = 'restaurant'
) x
) sub
ORDER BY school_id, (type <> 'school'), type, osm_id;
これはではありません 元のクエリと同じですが、実際に必要なものは、コメントでの議論による :
したがって、このクエリはそれらの学校のリストを返し、その後に近くのバーやレストランが続きます。行の各セットは、 osm_id
によってまとめられています。 列school_id
の学校の 。
現在、 LATERAL
を使用しています 結合し、空間GiSTインデックスを利用します。
テーブルスクール
SELECT * FROM school
の省略形です :
式(type <>'school')
次の理由により、各セットの学校を最初に注文します。
サブクエリsub
最後のSELECT
この式で注文する場合にのみ必要です。 UNION
クエリは、添付された ORDER BY
を制限します 列のみにリストし、式はありません。
この回答の目的で提示したクエリに焦点を当てます-無視 他の70のテキスト列のいずれかでフィルタリングするための拡張要件。それは本当に設計上の欠陥です。検索条件は少数に集中する必要があります 列。または、70列すべてにインデックスを付ける必要があり、私が提案するような複数列のインデックスはほとんどオプションではありません。それでも可能 でも...
インデックス
既存のものに加えて:
"idx_planet_osm_point_waygeo" gist (way_geo)
常に同じ列でフィルタリングする場合は、 を作成できます。複数列のインデックス 関心のあるいくつかの列をカバーしているので、 index-スキャンのみ 可能になる:
CREATE INDEX planet_osm_point_bar_idx ON planet_osm_point (amenity, name, osm_id)
Postgres 9.5
今後のPostgres9.5 主な改善点を紹介します それはたまたまあなたのケースに正確に対処します:
それはあなたにとって特に興味深いことです。これで、シングルを作成できます 複数列(カバー)GiSTインデックス:
CREATE INDEX reservations_range_idx ON reservations
USING gist(amenity, way_geo, name, osm_id)
そして:
そして:
なんで? ROLLUP コード>
私が提案したクエリを単純化するでしょう。関連する回答:
最初のアルファバージョンは2015年7月2日にリリースされました。
基本
もちろん、基本を見逃さないように注意してください: