2017-12-26 25 views
1

私の国のOSMデータをgeofabrik.deからダウンロードし、Ubuntu 16.04にインストールされたPostgreSQL 9.6にインポートして何回も使用しました。私も正しく動作するWebアプリケーションを作成しました。そこで、いくつかのポイントから一番近い特別なポイント(レストランなど)を返す別の機能を追加することにしました。一番近い点については動作しますが、それらの戻り値の配列が必要な場合は動作しません。だから私は私の問題を分解し、奇妙な行動を見つけました。私は次のクエリを実行する場合:PostgreSQL 9.6のウィンドウ機能での不安定なクエリの動作

SELECT t.osm_id 
     FROM (
     SELECT DISTINCT ON (a.points) a.points, v.osm_id AS osm_id, MIN(ST_DISTANCE(v.the_geom, a.points)) OVER (PARTITION BY a.points ORDER BY ST_DISTANCE(v.the_geom, a.points)) 
     FROM (SELECT ST_GEOMFROMEWKT('SRID=4326;POINT(17.104854583740238 48.15099866770469)') AS points) a 
     CROSS JOIN ways_vertices_pgr v 
    ) AS t 

をそれが返されます。

| osm_id   | 
| ----------------- | 
| 2338524511  | 

私は地図上にポイントを表示する場合、それは遠く離れて原点から配置され、私はサブクエリでポイントを変更した後、結果が残っています同じ。また、表示された点と元の点の間には多くの点があり、問合せによって戻されるはずです。

SELECT t.*, t.osm_id 
     FROM (
     SELECT DISTINCT ON (a.points) a.points, v.osm_id AS osm_id, MIN(ST_DISTANCE(v.the_geom, a.points)) OVER (PARTITION BY a.points ORDER BY ST_DISTANCE(v.the_geom, a.points)) 
     FROM (SELECT ST_GEOMFROMEWKT('SRID=4326;POINT(17.104854583740238 48.15099866770469)') AS points) a 
     CROSS JOIN ways_vertices_pgr v 
    ) AS t 

、それが返されます:それから私は、クエリ次の実行を試みたSELECT一部を除いて

| points            | osm_id | min     | osm_id  | 
| -------------------------------------------------- | -------- | -------------------- | -------- | 
| 0101000020E6100000010000C0D71A3140FFC3A1EC53134840 | 33169309 | 0.000124886435658481 | 33169309 | 

全体のクエリは同じままですが、結果は異なっており、今では正しいです。誰も私にどのように正しく動作するようにクエリを変更することをお勧めできますか?

+0

この 'CROSS JOINの目的は何ですか?ways_vertices_pgr v'あなたは本当にカルテンス製品を望んでいますか、それとも1列*スカラー*テーブルですか? – wildplasser

+0

subselectには、この点だけでなく、複数の点が含まれる可能性があるためです。しかし、どちらの場合も行動は変です。 – 32cupo

+0

st_within()またはst_distance()を使用して結合してみませんか? #strangebehaviour – wildplasser

答えて

2

distinct onを使用する場合は、order byが必要です。私は、これはあなたが最初のクエリのためにしたいの論理だと思う:

SELECT DISTINCT ON (a.points) a.points, v.osm_id AS osm_id,ST_DISTANCE(v.the_geom, a.points) as dist 
    FROM (SELECT ST_GEOMFROMEWKT('SRID=4326;POINT(17.104854583740238 48.15099866770469)') AS points) a CROSS JOIN 
     ways_vertices_pgr v 
    ORDER BY a.points, dist; 
+0

はいこれは、関係が1からNまで(N個の特定の点に最も近いN点)のときに完全に機能します。しかし、関係がMからN(N個の特定の点に近いN点)の場合、2点間の距離によって順序付けられたウィンドウ関数を使用する必要があります。 – 32cupo

+2

複数のポイントが必要な場合は、 'distinct on'を使用しません。 –

+0

はい、そうですね。 @ jeremy-schneiderの答えの後、私はあなたの答えが本当に意味するものを理解しています。今私は 'DISTINCT ON'は役に立たず、あなたが言及した順序で窓関数として 'MIN'だけを使うべきだと思う。私はそれを次の日に試し、結果をここに書きます。 – 32cupo

2

は、あなたが列を追加するときの結果が変化している理由を正確に確認するためにクエリをEXPLAIN ANALYZEの出力を確認してください。おそらく、行の順序に影響を与えるわずかに異なる実行計画を使用している可能性があります。

DISTINCT ONは定義によると、結果が実行間で変更される可能性があることを意味します。

SELECT DISTINCT ON ...クエリがDISTINCTフィルタに到着した行のユニークな順序を保証するために十分な列でソートされていない限り、セットの「最初の行は」予測不可能であることに注意してください:the PostgreSQL 9.6 manualから。 (DISTINCT ON処理は、ソートORDER BYの後に発生します。)ゴードンはあなたに再現性のある結果を与える必要があります示唆されているように

ORDER BYを追加します。

+0

実行計画をチェックしたので、 @ gordon-linoffが示唆しているように動作します。あなたの答えをありがとう、その後私は彼が本当に彼の提案によって意味を理解した。 – 32cupo

関連する問題