2010-12-02 45 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`) 
) 

我想返回一個行的每個停止時間去下一站。

我試圖與此查詢:

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 

但是,接縫組不工作及結果如下:

+------------+------------+----------+----------+------+ 
| 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 | 
+------------+------------+----------+----------+------+ 

如果我這樣做:

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 |  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的next_stop子停止查詢以應對多種途徑

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 
1

你打算改變模式嗎?如果是這樣,只需添加一個包含順序整數的列,就可以使該查詢變得更簡單,更高效。

如果沒有,這將做到這一點。

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 2010-12-02 16:27:07

+0

@Natim - 我認爲你用`api_routestop`替換了`yourtable`? – 2010-12-02 16:30:54

+0

好的,這很神奇。 – Natim 2010-12-02 16:45:40

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