如何使用想要的结果进行GROUP BY?

时间:2010-12-02 15:03:42

标签: sql mysql

基本上,我有一张包含time_from_start值的路线的所有巴士站的表格,这有助于使它们处于良好状态。

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`)
)

我想在一行的每个站点返回到下一站的时间。

我试过这个QUERY:

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获得第一个结果?

3 个答案:

答案 0 :(得分:2)

你得到了很多结果,因为你的每一站都在同一条路线上的每一站都加入了。

因此,您需要将“下一个”停靠点识别为具有相同路径ID但距离当前路径起点晚的最短时间的停靠点

更新将routeId添加到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 :(得分: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

答案 2 :(得分: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