19

いくつかのGTFSデータを使用しており、ルートによって提供される関連するすべての停車地のリストを作成できるようにしたいと考えています。GTFSデータの扱い方がよくわかりません。

Trips.txtは、次のような形式で提供されます。

route_id,service_id,trip_id,trip_headsign,direction_id,block_id,shape_id 1,A20120610WKD,A20120610WKD_000800_1..S03R,SOUTH FERRY,1,,1..S03R 1,A20120610WKD,A20120610WKD_002700_1..S03R,SOUTH FERRY,1,,1..S03R 1,A20120610WKD,A20120610WKD_004700_1..S03R,SOUTH FERRY,1,,1..S03R 1,A20120610WKD,A20120610WKD_006700_1..S03R,SOUTH FERRY,1,,1..S03R 1,A20120610WKD,A20120610WKD_008700_1..S03R,SOUTH FERRY,1,,1..S03R

shape_idを使用して一致する形状を読み取ってから、緯度と経度が一致するストップを探してみましたが、それは確実に機能しないようです。誰かがこれを行う方法を知っていますか?

4

6 に答える 6

44

お気付きのように、GTFS ではルートとストップの間に直接的な関係はありません。代わりに、ストップはトリップに関連付けられます。各トリップは、特定のルートに沿った車両の単一の「走行」を表します。これは、ルートが必ずしもすべての停留所を常に提供しているわけではないという事実を反映しています。たとえば、週末には、高校の外の停留所をスキップすることがあります。

したがって、ルートが提供するすべてのストップのリストを取得するには、いくつかのモデルを組み合わせる必要があります。

  • routes.txt関心のあるルートのルート ID を提供します。
  • trips.txtそのルートのトリップ ID のセットを提供します。
  • stop_times.txtこれらの各ルートで提供される停車地の一連の停車地 ID を提供します。
  • stops.txtでは、これらの各停留所に関する情報を提供します。

SQL データベースを使用して GTFS データを保存していると仮定すると、(ルート ID を取得したら) 次のようなクエリを使用できます。

SELECT stop_id, stop_name FROM stops WHERE stop_id IN (
  SELECT DISTINCT stop_id FROM stop_times WHERE trip_id IN (
    SELECT trip_id FROM trips WHERE route_id = <route_id>));

ただし、これにより、ルートがこれまでに提供したすべてのストップのレコードが出力されることに注意してください。乗客のスケジュール情報を生成している場合は、クエリを今日実行されるルートのみに制限し、たとえば、次の 30 分後に出発する停車時刻のみに制限することをお勧めします。


更新:上記の SQL クエリは、GTFS モデル間の関係を最も簡単に示していると感じた方法で記述しましたが、btse は正しい (以下の彼の回答で) このようなクエリは実際には本番環境で使用されることはありません。遅すぎる。代わりに、テーブルの結合とインデックスを使用して、クエリ時間を適切に保ちます。

以下は、実際のアプリケーションにコピー アンド ペーストするのにより適した方法で記述された、同等のクエリです。

SELECT DISTINCT stops.stop_id, stops.stop_name
  FROM trips
  INNER JOIN stop_times ON stop_times.trip_id = trips.trip_id
  INNER JOIN stops ON stops.stop_id = stop_times.stop_id
  WHERE route_id = <route_id>;

JOIN通常、 orWHERE節で使用される各列のインデックスも作成します。この場合、次のことを意味します。

CREATE INDEX stop_times_trip_id_index ON stop_times(trip_id);

CREATE INDEX trips_route_id_index ON trips(route_id);

(通常、RDBMS は主キーによって各テーブルに自動的にインデックスを付けるため、 にインデックスを明示的に作成する必要はありませんstops.stop_id。)

使用中の特定の DBMS と、パフォーマンスのためにディスク領域を犠牲にする意思に応じて、さらに多くの最適化が可能です。しかし、これらのコマンドは、明確さを不必要に犠牲にすることなく、ほぼすべての RDBMS で優れたパフォーマンスを発揮します。

于 2012-11-30T18:38:50.407 に答える
10

Google 検索でこの投稿に出くわしたので、他の誰かが偶然見つけた場合に備えて、より良い回答で更新すると考えました。Simon の答えは 100% 正しいですが、彼が提供したクエリは大規模な GTFS フィードに対して非常に低速です。同じことを行うクエリを次に示しますが、パフォーマンスは大幅に高速です。

事例証拠として、約 50 MB の GTFS フィードの場合、Simon のクエリが完了するまでに 10 ~ 25 秒かかりました。以下のステートメントは、一貫して 0.2 秒未満かかります。

SELECT T3.stop_id, T3.stop_name 
FROM trips AS T1
JOIN
stop_times AS T2
ON T1.trip_id=T2.trip_id AND route_id = <routeid>
JOIN stops AS T3
ON T2.stop_id=T3.stop_id
GROUP BY T3.stop_id, T3.stop_name

アップデート:

前にこれについて言及しなかったことに気付きましたが、もちろん、各テーブルが結合されているインデックスが必要になるでしょう。

于 2013-07-05T16:53:32.497 に答える
3

GROUP BY shape_idから選択するtripsと、クエリをさらに高速化できます。

@btse のクエリを使用して 2 つのルートの一意の停留所を取得すると、1.147 秒かかります。

私の同等のクエリには 0.4 秒かかります。

SELECT unique_stops.route_id, unique_stops.stop_id, stop_name, stop_desc, stop_lat, stop_lon
FROM
  stops,
  (SELECT stop_id, route_id
   FROM
     stop_times,
     (SELECT trip_id, route_id
      FROM trips
      WHERE route_id IN (801, 803)
      GROUP BY shape_id
     ) AS unique_trips
   WHERE stop_times.trip_id = unique_trips.trip_id
   GROUP BY stop_id) AS unique_stops
WHERE stops.stop_id = unique_stops.stop_id
于 2014-02-15T20:51:58.467 に答える