2016-07-03 6 views
0

У меня есть следующая таблица, представляющая шины и точки, в которых они останавливаются.Subselect в MySQL

bus_table 

bus stop_no station_id 
    1  1   1 
    1  2   2 
    1  3   3 
    2  1   7 
    2  2   8 
    2  3   9 
    3  1   3 
    3  2   4 
    3  3   5 
    3  4   6 
    3  5   7 

Я хочу, чтобы добраться от станции 1 до станции 9.

Что запрос я могу написать для этого?

+0

'SELECT * FROM query_test WHERE стат в (SELECT стат FROM query_test WHERE Name = 'b3');' это :) @sagi – b101

+0

это действительно работает, но у меня возникло ощущение, что это не правильный способ сделать это: 'SELECT * FROM bus_table WHERE stat IN (SELECT stat FROM bus_table WHERE Name = 'b3') AND NAME NOT like 'b3'; ' – b101

+0

Это проблема обхода графика. Многие базы данных поддерживают иерархические и рекурсивные запросы, поэтому такую ​​проблему можно решить с помощью одного 'select'. MySQL не является одной из этих баз данных. Вам нужно будет написать хранимую процедуру. –

ответ

1

В качестве примера. Очевидно, что это решение не является рекурсивным - но вы могли бы просто держать перебор автобусных маршрутов, пока вы не получили от А до В.

DROP TABLE IF EXISTS bus_routes; 


CREATE TABLE bus_routes 
(bus_no INT NOT NULL 
,stop_no INT NOT NULL 
,station_id INT NOT NULL 
,PRIMARY KEY(bus_no,stop_no) 
); 

INSERT INTO bus_routes VALUES 
(1,1,1), 
(1,2,2), 
(1,3,3), 
(2,1,7), 
(2,2,8), 
(2,3,9), 
(3,1,3), 
(3,2,4), 
(3,3,5), 
(3,4,6), 
(3,5,7); 

SELECT a_from.bus_no 
    , a_from.station_id start_from 
    , b_from.station_id first_change_at 
    , b_from.bus_no to_bus 
    , c_from.station_id then_change_at 
    , c_from.bus_no to_bus 
    , c_to.station_id alighting_at 
    FROM bus_routes a_from 
    JOIN bus_routes a_to 
    ON a_to.bus_no = a_from.bus_no 
    AND a_to.stop_no > a_from.stop_no 
    JOIN bus_routes b_from 
    ON b_from.station_id = a_to.station_id 
    JOIN bus_routes b_to 
    ON b_to.bus_no = b_from.bus_no 
    AND b_to.stop_no > b_from.stop_no 
    JOIN bus_routes c_from 
    ON c_from.station_id = b_to.station_id 
    JOIN bus_routes c_to 
    ON c_to.bus_no = c_from.bus_no 
    AND c_to.stop_no > c_from.stop_no 
WHERE a_from.station_id = 1 
    AND c_to.station_id = 9; 

+--------+------------+-----------------+--------+----------------+--------+--------------+ 
| bus_no | start_from | first_change_at | to_bus | then_change_at | to_bus | alighting_at | 
+--------+------------+-----------------+--------+----------------+--------+--------------+ 
|  1 |   1 |    3 |  3 |    7 |  2 |   9 | 
+--------+------------+-----------------+--------+----------------+--------+--------------+ 
+0

Если бы таблица увеличивалась в количестве шин, увеличилось бы количество Joins или просто, если бы шины разделили станции? Я не уверен, будет ли этот ответ работать, если количество автобусов будет неизвестно. (Я не просил об этом в моем первоначальном вопросе, вот почему я принял этот ответ, поскольку он работает) – b101

0

Рекурсивного обход графа автобусных остановок (проверен на MSSQL 2016 г.):

DECLARE @from NCHAR(4) = 'ort1'; 
DECLARE @to NCHAR(4) = 'ort9'; 

WITH [route] ([path], [lastBus], [current]) 
AS 
    (SELECT CAST(N'' AS NVARCHAR(1000)) AS [path], CAST(N'' AS NCHAR(2)) AS [lastBus], @from AS [current] 
    UNION ALL 
    SELECT CAST(cur.[path] + N',' + busesAvailable.name + N' to ' + [next].stat AS NVARCHAR(1000)) AS [path], 
     busesAvailable.name AS [lastBus], 
     [next].stat AS [current] 
    FROM [route] cur 
    INNER JOIN dbo.BusStat busesAvailable ON busesAvailable.stat = cur.[current] AND busesAvailable.name <> cur.[lastBus] 
    INNER JOIN dbo.BusStat [next] 
     ON [next].stat <> cur.[current] 
     AND [next].name = busesAvailable.name) 
SELECT TOP 1 [route].[path] 
FROM [route] 
WHERE [route].[current] = @to; 

, что с учетом таблицы создается с:

CREATE TABLE [dbo].[BusStat] 
(
    [name] NCHAR (2) NOT NULL, 
    [stat] NCHAR (4) NOT NULL 
); 
INSERT INTO [dbo].[BusStat] ([name], [stat]) 
SELECT 'b1', 'ort1' UNION ALL 
SELECT 'b1', 'ort2' UNION ALL 
SELECT 'b1', 'ort3' UNION ALL 
SELECT 'b2', 'ort7' UNION ALL 
SELECT 'b2', 'ort8' UNION ALL 
SELECT 'b2', 'ort9' UNION ALL 
SELECT 'b3', 'ort3' UNION ALL 
SELECT 'b3', 'ort4' UNION ALL 
SELECT 'b3', 'ort5' UNION ALL 
SELECT 'b3', 'ort6' UNION ALL 
SELECT 'b3', 'ort7';