sql - 如何用想要的结果做这个 GROUP BY?

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

我想为线路的每一站返回到下一站的时间。

我试过这个查询:

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

最佳答案

您会得到很多返回结果,因为您将同一路线上的每个停靠点都连接到其他每个停靠点。

因此您需要将“下一个”停靠点标识为具有相同路线 ID 但距开始的最短时间晚于当前停靠点的停靠点

更新 next_stop 子查询中添加routeId,以处理站点在多条 route 使用的情况

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

关于sql - 如何用想要的结果做这个 GROUP BY?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4336378/

相关文章:

c# - 无法解析为有效的类型或函数

PHP(编辑和删除 html 文件)

php - 检查sql数据库中是否存在email,然后输出(关于running if inside if)

c# - 无效的阅读尝试 - 可以使用 Action 吗?

即使有索引,mysql 文件排序也会发生 -- 我该如何修复

mysql - 插入到值具有子查询的表中并返回多行

sql - 具有两列的 T-SQL 顺序更新

mysql - 如何使用 Sequelize 和 MySQL 在 JSON 列的 SELECT 上使用 LOWER?

mysql - 我想要列的最小编号

C#/SQL 获取所有存储过程及其代码