我有以下表格:
ROUTE表中的一行将包含列车编号,它的到达和离开时间(如果该站是第一个/最后一个,则为这两个中的一个)和station_id。
我想找出每个train_number,它走哪条路径。我的困难在于确定每条路线的到达和离开站名称。
例如,列车1337可能具有以下路径:
我想弄清楚这些路径,即stationA - > stationB - > stationC等。
如何实现(如果重要的话,我正在使用Oracle SQL)?
对于stationA(获取路线的开始)我可以执行以下操作:
SELECT name FROM STATION
WHERE station.id = ROUTE.station_id AND ROUTE.arrival IS NULL
答案 0 :(得分:4)
设定:
CREATE TABLE STATION (
id NUMBER PRIMARY KEY,
name VARCHAR2(20),
city VARCHAR2(20)
);
CREATE TABLE SERVICE (
train_number NUMBER PRIMARY KEY,
train_name VARCHAR2(20)
);
CREATE TABLE ROUTE (
id NUMBER PRIMARY KEY,
train_number NUMBER REFERENCES SERVICE( train_number ),
station_id NUMBER REFERENCES STATION( id ),
arrival_time NUMBER,
departure_time NUMBER
);
INSERT INTO STATION VALUES ( 1, 'stationA', 'city1' );
INSERT INTO STATION VALUES ( 2, 'stationB', 'city1' );
INSERT INTO STATION VALUES ( 3, 'stationC', 'city2' );
INSERT INTO STATION VALUES ( 4, 'stationD', 'city3' );
INSERT INTO SERVICE VALUES ( 1337, 'train1' );
INSERT INTO SERVICE VALUES ( 1338, 'train2' );
INSERT INTO SERVICE VALUES ( 1339, 'train3' );
INSERT INTO ROUTE VALUES (1, 1337, 1, null, 1800);
INSERT INTO ROUTE VALUES (2, 1337, 2, 1900, 2000);
INSERT INTO ROUTE VALUES (3, 1337, 3, 2020, 2100);
INSERT INTO ROUTE VALUES (4, 1337, 4, 2120, 2200);
INSERT INTO ROUTE VALUES (5, 1338, 1, null, 1800);
INSERT INTO ROUTE VALUES (6, 1338, 4, 1900, 2000);
INSERT INTO ROUTE VALUES (7, 1338, 3, 2020, 2100);
INSERT INTO ROUTE VALUES (8, 1338, 2, 2120, 2200);
查询:
WITH INDEXED_ROUTES AS (
SELECT train_number,
s.name,
ROW_NUMBER() OVER( PARTITION BY train_number ORDER BY COALESCE( arrival_time, 0 ), COALESCE( departure_time, 2400 ) ) AS IDX
FROM ROUTE r
INNER JOIN
STATION s
ON ( r.station_id = s.id )
)
SELECT train_number,
SUBSTR( SYS_CONNECT_BY_PATH( NAME, ' -> ' ), 5 ) AS route
FROM indexed_routes
WHERE CONNECT_BY_ISLEAF = 1
START WITH IDX = 1
CONNECT BY PRIOR IDX + 1 = IDX
AND PRIOR train_number = train_number;
或者:
SELECT train_number,
LISTAGG( s.name, ' -> ' ) WITHIN GROUP ( ORDER BY arrival_time ASC NULLS FIRST ) AS route
FROM ROUTE r
INNER JOIN
STATION s
ON ( r.station_id = s.id )
GROUP BY train_number;
要么输出:
TRAIN_NUMBER ROUTE
------------ --------------------------------------------
1337 stationA -> stationB -> stationC -> stationD
1338 stationA -> stationD -> stationC -> stationB
如果您只想要成对的电台,请使用LAG
或LEAD
分析函数:
SELECT train_number,
LAG( s.name ) OVER( PARTITION BY train_number ORDER BY COALESCE( arrival_time, 0 ), COALESCE( departure_time, 2400 ) ) AS prev_station_name,
s.name AS station_name
FROM ROUTE r
INNER JOIN
STATION s
ON ( r.station_id = s.id );
输出:
TRAIN_NUMBER PREV_STATION_NAME STATION_NAME
------------ -------------------- --------------------
1337 (null) stationA
1337 stationA stationB
1337 stationB stationC
1337 stationC stationD
1338 (null) stationA
1338 stationA stationD
1338 stationD stationC
1338 stationC stationB
答案 1 :(得分:1)
如果路径中没有分支,那么问题只是在到达或离开时间点订站:
SELECT s.station_id, name FROM ROUTE r INNER JOIN STATION s r.station_id = s.station_id ON WHERE train_number = 1 ORDER BY departure_time
答案 2 :(得分:1)
在MySQL中,您可以使用按到达时间排序的group_concat
,以逗号分隔列表的形式获取每列火车的路径。
例如:
select train_number, group_concat(name order by arrival_time asc)
from route join station
on route.station_id=station.id
group by train_number
order by train_number;
输出如下:
1337 stationA,stationB,stationC,stationD
在Oracle(来自11g第2版)中,以下查询将产生相同的输出:
select train_number, LISTAGG(name, ',') WITHIN GROUP (ORDER BY arrival_time ASC NULLS FIRST)
from route join station
on route.station_id=station.id
group by train_number
order by train_number;