这是我的表:
ROUTES = the route ID
STATIONS = the station ID
STOPS? = if the train stops at this station then is equal to 1 otherwise 0
-------------------------
ROUTES STATIONS STOPS?
-------------------------
R1 S1 1
R1 S2 0
R1 S3 1
R1 S4 0
R1 S5 1
R2 S1 1
R2 S2 1
R2 S3 1
R2 S4 0
R2 S5 1
R3 S1 1
R3 S2 0
R3 S4 1
R3 S5 0
R3 S6 1
R3 S7 1
R4 S1 1
R4 S2 1
R4 S3 0
R4 S4 1
R5 S2 1
R5 S3 0
R5 S4 1
我想要做的是找出哪些路线经过相同的车站,但没有相同的车站。
例如: 我们看到了
Route R1 passes through stations S1->S2->S3->S4->S5
Route R2 passes through stations S1->S2->S3->S4->S5
但它们有不同的停止点,因此结果应为:
R1
R2
我想先将所有路线分组,并将属于该组的STATIONS与其他所有路线进行比较,并检查它们是否至少有一个不同的停靠点。
答案 0 :(得分:0)
以下查询将返回其中一列列车未停止的路线和车站http://sqlfiddle.com/#!3/f4c5f/8。
SELECT DISTINCT
tblRoutes.ROUTES
,tblRoutesCross.ROUTES CrossingRoute
,tblRoutes.STATIONS
FROM
tblRoutes
INNER JOIN
tblRoutes tblRoutesCross
ON
tblRoutesCross.STATIONS = tblRoutes.STATIONS
AND
tblRoutes.ROUTES < tblRoutesCross.ROUTES
AND
(
tblRoutesCross.STOPS = 0
OR
tblRoutes.STOPS = 0
)
以下查询将仅返回过境路线:
SELECT DISTINCT
tblRoutes.ROUTES
,tblRoutesCross.ROUTES CrossingRoute
--,tblRoutes.STATIONS
FROM
tblRoutes
INNER JOIN
tblRoutes tblRoutesCross
ON
tblRoutesCross.STATIONS = tblRoutes.STATIONS
AND
tblRoutes.ROUTES < tblRoutesCross.ROUTES
AND
(
tblRoutesCross.STOPS = 0
OR
tblRoutes.STOPS = 0
)
要查找非列车停止改变的路线或者在哪里找到路线:
SELECT DISTINCT
tblRoutes.ROUTES
,tblRoutesCross.ROUTES CrossingRoute
--,tblRoutes.STATIONS
FROM
tblRoutes
INNER JOIN
tblRoutes tblRoutesCross
ON
tblRoutesCross.STATIONS = tblRoutes.STATIONS
AND
tblRoutes.ROUTES < tblRoutesCross.ROUTES
AND
(
tblRoutesCross.STOPS = 0
AND
tblRoutes.STOPS = 0
)
答案 1 :(得分:0)
我很抱歉我的代码,但我正在工作,我会稍后格式化,但这是你需要的步骤
希望它有所帮助
DECLARE @table TABLE (r NVARCHAR(3), s NVARCHAR(3), st BIT)
DECLARE @temp TABLE (r NVARCHAR(3), s NVARCHAR(100), st NVARCHAR(100))
INSERT INTO @table
( [r], [s], [st] )
VALUES ('R1','S1',1 ),
('R1','S2',0),
('R1','S3',1),
('R1','S4',0),
('R1','S5',1),
('R2','S1',1),
('R2','S2',1),
('R2','S3',1),
('R2','S4',0),
('R2','S5',1),
('R3','S1',1),
('R3','S2',0),
('R3','S4',1),
('R3','S5',0),
('R3','S6',1),
('R3','S7',1),
('R4','S1',1),
('R4','S2',1),
('R4','S3',0),
('R4','S4',1),
('R5','S2',1),
('R5','S3',0),
('R5','S4',1)
SELECT * FROM @table
INSERT INTO @temp
( [r], [s], [st] )
SELECT DISTINCT r ,(
Select s + ',' AS 'data()'
From @table R2
WHERE R2.[r] = [R].r
ORDER BY [r]
For XML PATH ('') ) [Routs]
, (
Select CAST([st]AS NVARCHAR(2)) + ',' AS 'data()'
From @table R2
WHERE R2.[r] = [R].r
ORDER BY [r]
For XML PATH ('') ) [Stops]
FROM @table R
SELECT * FROM @temp
SELECT * FROM @temp WHERE [s] IN (SELECT [s] FROM @temp GROUP BY s HAVING COUNT(*) > 1 )
SELECT T.* FROM @temp T
INNER JOIN (
SELECT [s], [st] FROM @temp WHERE [r] IN (
SELECT [r] FROM @temp WHERE [s] IN
( SELECT [s] FROM @temp GROUP BY s HAVING COUNT(*) > 1 ) )
GROUP BY [s], [st] HAVING COUNT (*) = 1 ) X ON T.[s] = X.[s] AND T.[st] = X.[st]
答案 2 :(得分:0)
我假设一个TrainRoutes表,每个R1,R2等都有一行。如果需要,可以用Stops中的select distinct RouteID替换它。
Select
r1.RouteID Route1,
r2.RouteID Route2
From
-- cross to compare each route with each route
dbo.TrainRoutes r1
Cross Join
dbo.TrainRoutes r2
Inner Join
dbo.Stops s1
On r1.RouteID = s1.RouteID
Inner Join
dbo.Stops s2
On r2.RouteID = s2.RouteID
Where
r1.RouteID < r2.RouteID -- no point in comparing R1 with R2 and R2 with R1
Group By
r1.RouteID,
r2.RouteID
Having
-- check each route has the same number of stations
count(Distinct s1.stationID) = count(Distinct s2.stationID) And
-- check each route has the same stops
Sum(Case When s1.StationID = s2.StationID Then 1 Else 0 End) = count(Distinct s1.StationID) And
-- check each route has different halts
sum(Case When s1.StationID = s2.StationID And s1.Halts = s2.Halts Then 1 Else 0 End) != count(Distinct s1.StationID)
您也可以在没有TrainRoute表的情况下执行此操作,但现在您正在交叉连接两个较大的表:
Select
s1.RouteID Route1,
s2.RouteID Route2
From
dbo.Stops s1
Cross Join
dbo.Stops s2
Where
s1.RouteID < s2.RouteID
Group By
s1.RouteID,
s2.RouteID
Having
count(Distinct s1.stationID) = count(Distinct s2.stationID) And
Sum(Case When s1.StationID = s2.StationID Then 1 Else 0 End) = count(Distinct s1.StationID) And
sum(Case When s1.StationID = s2.StationID And s1.Halts = s2.Halts Then 1 Else 0 End) != count(Distinct s1.StationID)
答案 3 :(得分:0)
这里真正的挑战是找到经过相同站点的路线。我们的想法是通过在桌面上进行自我联接来比较两条路线,即compa和compb。当然,这种比较着眼于所有对。
现在,如果我们汇总一些有关路线的信息,我们可以确定它们是否具有相同的站点:
第一个是连接的条件,第二个是使用窗口函数处理以在连接之前进行计数,第三个是连接的结果。
当所有这些计数相同时,两条路线通过同一站。
够容易。现在我们只需要添加一些站点在一条路线上停靠但不在另一条路线上的站点。
以下查询包含此逻辑:
select compa_Route, compb_Route
from (select compa.route as compa_route, compb.route as compb_Route,
MAX(compa.numstations) as compa_NumStations,
MAX(compb.NumStations) as compb_NumStations,
SUM(case when compa.stop <> compb.stop then 1 else 0 end) as DifferentStops,
COUNT(*) as both_NumStations
from (select t.*, COUNT(*) over (partition by route) as numstations
from t
) routea join
(select t.*, COUNT(*) over (partition by route) as numstations
from t
) routeb
on routea.station = routeb.station and
routea.route < routeb.route
group by compa.route, compb.route
) ab
where compa_NumStations = compb_NumStations and
compa_NumStations = both_NumStations and
DifferentStops > 0
请注意,这假设站点不会在路线上重复。如果站点可以重复,那么问题就会变得有点困难。
答案 4 :(得分:0)
在SQLServer2005 +中使用递归CTE(公用表表达式)来查找所有站点并总结列车停靠点来比较它们
;WITH cte (id, r, s, st, max_level) AS
(
SELECT ROW_NUMBER() OVER(PARTITION BY t.r ORDER BY (SELECT 1)) as id,
t.r, t.s, t.st,
COUNT(*) OVER(PARTITION BY t.r) AS max_level
FROM dbo.test11 t
), cte2 (id, r, s, st, max_level) AS
(
SELECT id, r, s, st, max_level
FROM cte
WHERE id = 1
UNION ALL
SELECT c.id, c.r, CAST(ISNULL(ct.s, '') + ', ' + ISNULL(c.s, '') AS nvarchar(100)) AS s,
ct.st + c.st, c.max_level
FROM cte c JOIN cte2 ct ON c.id = ct.id + 1 AND c.r = ct.r
)
SELECT c.r, c.s, c.st
FROM cte2 c JOIN cte2 ct ON c.s = ct.s AND c.r <> ct.r AND c.st <> ct.st
WHERE c.id = c.max_level AND ct.id = ct.max_level
SQLFiddle上的演示
答案 5 :(得分:-1)
只搜索没有余数的关系部门或确切的关系部门。