2010-12-02 12 views
0

基本的には、time_from_startの値を持つルートのすべてのバス停を持つテーブルがあり、それを適切な順序で配置するのに役立ちます。希望の結果でこのGROUP BYを行うには?

CREATE TABLE `api_routestop` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `route_id` int(11) NOT NULL, 
    `station_id` varchar(10) NOT NULL, 
    `time_from_start` int(11) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `api_routestop_4fe3422a` (`route_id`), 
    KEY `api_routestop_15e3331d` (`station_id`) 
) 

次の停止に行く時間を1行ごとに戻したいと思います。

私はこのクエリを使用してみました:

SELECT r1.station_id, r2.station_id, r1.route_id, COUNT(*), (r2.time_from_start - r1.time_from_start) as time 
FROM api_routestop r1 
LEFT JOIN api_routestop r2 ON r1.route_id = r2.route_id AND r1.id <> r2.id 
GROUP BY r1.station_id 
HAVING time >= 0 
ORDER BY r1.route_id, r1.time_from_start, r2.time_from_start 

しかし、縫い目によってグループが動作しないと結果は以下のようになります。

SELECT r1.station_id, r2.station_id, r1.route_id, COUNT(*), (r2.time_from_start - r1.time_from_start) as time 
FROM api_routestop r1 
LEFT JOIN api_routestop r2 ON r1.route_id = r2.route_id AND r1.id <> r2.id 
GROUP BY r1.station_id, r2.station_id, r1.route_id 
HAVING time >= 0 
ORDER BY r1.route_id, r1.time_from_start, r2.time_from_start 

:私はそれを行う場合

+------------+------------+----------+----------+------+ 
| station_id | station_id | route_id | COUNT(*) | time | 
+------------+------------+----------+----------+------+ 
| Rub01  | Sal01  |  1 |  16 | 1 | 
| Lyc02  | Sch02  |  2 |  17 | 2 | 
| Paq01  | PoB01  |  3 |  15 | 1 | 
| LaT02  | Gco02  |  4 |  16 | 1 | 
| Sup01  | Tur01  |  5 |  132 | 1 | 
| Oeu02  | CtC02  |  6 |  20 | 2 | 
| Ver02  | Elo02  |  7 |  38 | 1 | 
| Can01  | Mbo01  |  8 |  70 | 1 | 
| Ver01  | Elo01  |  9 |  77 | 1 | 
| MCH01  | for02  |  10 |  77 | 1 | 
+------------+------------+----------+----------+------+ 

私は近づいています:

+------------+------------+----------+----------+------+ 
| station_id | station_id | route_id | COUNT(*) | time | 
+------------+------------+----------+----------+------+ 
| Rub01  | Sal01  |  1 |  1 | 1 | 
| Rub01  | ARM01  |  1 |  1 | 2 | 
| Rub01  | MaV01  |  1 |  1 | 4 | 
| Rub01  | COl01  |  1 |  1 | 5 | 
| Rub01  | Str01  |  1 |  1 | 6 | 
| Rub01  | Jau01  |  1 |  1 | 7 | 
| Rub01  | Cdp01  |  1 |  1 | 9 | 
| Rub01  | Rep01  |  1 |  1 | 11 | 
| Rub01  | CoT01  |  1 |  1 | 12 | 
| Rub01  | Ctr01  |  1 |  1 | 14 | 
| Rub01  | FLy01  |  1 |  1 | 15 | 
| Rub01  | Lib01  |  1 |  1 | 17 | 
| Rub01  | Bru01  |  1 |  1 | 18 | 
| Rub01  | Sch01  |  1 |  1 | 20 | 
| Rub01  | Lyc01  |  1 |  1 | 22 | 
| Rub01  | Res01  |  1 |  1 | 24 | 
| Sal01  | ARM01  |  1 |  1 | 1 | 
| Sal01  | MaV01  |  1 |  1 | 3 | 
| Sal01  | COl01  |  1 |  1 | 4 | 
| Sal01  | Str01  |  1 |  1 | 5 | 
| Sal01  | Jau01  |  1 |  1 | 6 | 
| Sal01  | Cdp01  |  1 |  1 | 8 | 
| Sal01  | Rep01  |  1 |  1 | 10 | 
| Sal01  | CoT01  |  1 |  1 | 11 | 
| Sal01  | Ctr01  |  1 |  1 | 13 | 
| Sal01  | FLy01  |  1 |  1 | 14 | 
| Sal01  | Lib01  |  1 |  1 | 16 | 
| Sal01  | Bru01  |  1 |  1 | 17 | 
| Sal01  | Sch01  |  1 |  1 | 19 | 
| Sal01  | Lyc01  |  1 |  1 | 21 | 
... 
3769 rows in set (0.07 sec) 

しかし、同じr1.station_idとr1.route_idの最初の結果しか持たないためにはどうすればよいですか?

答えて

2

あなたの取得すべてのストップが同じルート上の他のすべての停止に接合されたので、あなたが戻って結果の多くを取得しています。

だから、同じルートのIDを持っていますが、現在の1

更新next_stopサブに追加ルートIDより後に開始されてから最小の時間を持っているストップとして「次へ」停止を特定する必要があります複数のルートで使用する局の場合に対処するためのクエリ

SELECT 
    r1.station_id, 
    r2.station_id, 
    r1.route_id, 
    r2.time_from_start - r1.time_from_start as time 

FROM 
api_routestop r1 
INNER JOIN (SELECT 
     r1.station_id , r2.route_id, min(r2.time_from_start) next_time_from_start 
FROM 
    api_routestop r1 
    LEFT JOIN api_routestop r2 ON r1.route_id = r2.route_id AND r1.id <> r2.id 
     and r2.time_from_start > r1.time_from_start 
    GROUP BY r1.Station_id, r2.route_id) next_stop 

ON r1.Station_id = next_stop.station_id 
    and r1.route_id = next_stop.route_id 
LEFT JOIN api_routestop r2 
ON r2.time_from_start = r2.next_time_from_start 
    and r1.route_id = r2.route_id 
AND r2.time_from_start > r1.time_from_start 
+0

これは近いですが、私はまだいくつかの負の時間といくつかのr2.station_id = r1.station_idを持っています – Natim

+0

私はルート上のtime_from_startが一意であると仮定しました。これは悪い仮定だったのですか –

+0

実際、それは悪い仮定ではありませんでした。しかし、ラインの最後の停止は次のステップを持っていません。 – Natim

1

スキーマの変更はお済みですか?もしそうであれば、route上のすべての停止点に対して連続した整数を含む列を追加するだけで、このクエリはずっと簡単かつ効率的になります。

これが失敗することになります。

SELECT 
     station_id, 
     route_id, 
     time_from_start, 
     time_to_next 
FROM 
(
SELECT 
    station_id,route_id,time_from_start, 
    IF(@prev <> route_id, null, @time_from_start-time_from_start) AS time_to_next, 
    @time_from_start := time_from_start, 
    @prev := route_id 
    FROM api_routestop 
    JOIN (SELECT @time_from_start := NULL, @prev := 0) AS r 
    ORDER BY route_id, time_from_start DESC 
) t 
ORDER BY route_id,time_from_start 
+0

それはよさそうだが、私はそれを実行するために成功しませんでした。 – Natim

+0

@Natim - 'yourtable'を' api_routestop'に置き換えましたか? –

+0

大丈夫、それは魔法です。 – Natim

2
SELECT station_id, coalesce( 
    (SELECT time_from_start 
     FROM api_routestop t2 
    WHERE t2.time_from_start > t1.time_from_start 
     AND t2.time_from_start <= (SELECT time_from_start FROM api_routestop t5 WHERE t5.station_id = '4' AND t5.route_id=t1.route_id) 
     AND t2.route_id = t1.route_id 
    ORDER BY t2.time_from_start LIMIT 1), time_from_start) - time_from_start AS difference 
FROM api_routestop t1 
WHERE t1.route_id = 1 
    AND t1.time_from_start >= (SELECT time_from_start FROM api_routestop t4 WHERE t4.station_id = '2' AND t4.route_id=t1.route_id) 
    AND t1.time_from_start <= (SELECT time_from_start FROM api_routestop t5 WHERE t5.station_id = '4' AND t5.route_id=t1.route_id) 
ORDER BY time_from_start 
+0

LIMIT 1のいい使い方ですが、悲しいことにMYSQLでしか動作しません –

+0

MSSQLではこれは同じだと思いますが(SELECT TOP 1 time_from_start FROM(.....))。 LIMITも削除する必要があります。 – Peposh

+0

'SELECT t1.station_id、t1.route_id、((選択t2.time_from_start FROM api_routestop t2 WHERE t2.time_from_start> t1.time_from_start AND t2.route_id = t1.route_id ORDER BY t2.time_from_start LIMIT 1) - time_from_start)時刻として FROM api_routestop t1 ORDER BY t1.time_from_start'これはいいですが、次の停止のコードを返しません。 – Natim

関連する問題