to happyflystone:
老兄,有一条路径是1-2-3-4-5。
在这个示例中,还要考虑避免循环的情况,如 1,2;3,2;3,1;构成了循环。
我也曾考虑过将该数据集反向再和原数据集Union,这样就可以用一般的通用算法,但还是要考虑避免循环的问题,
该问题我曾发表在Oracle社区中,但Oracle的回答不能让我满意,我只好寻求Sql的解法,再转换过去。
注意:只能用在Sql2000中。
老兄,有一条路径是1-2-3-4-5。
在这个示例中,还要考虑避免循环的情况,如 1,2;3,2;3,1;构成了循环。
我也曾考虑过将该数据集反向再和原数据集Union,这样就可以用一般的通用算法,但还是要考虑避免循环的问题,
该问题我曾发表在Oracle社区中,但Oracle的回答不能让我满意,我只好寻求Sql的解法,再转换过去。
注意:只能用在Sql2000中。
解决方案 »
- csv文件导入问题
- 只采用SQL语言,能象raiseerror一样在客户端实现某功能完成后自动提示文本的功能吗?
- 企业管理器的图标不小心给删除了,怎么样才能弄一个新的出来呢?
- 请教日期分段SUM怎么写
- 感觉比较难的问题,寻高手
- sql server 2005重新安装程序选择不了sql server database services
- 重发此贴,希望问题能得到解决,焦急中...
- 为什么我的SQL SERVER不能启动呢?
- 用视图生成语句,产生的视图能否储存?,能否从视图结果得到原表的结构定义?
- SQLServer:怎么用bcp把sql查询结果备份到文件中?
- 求..创建维护计划时,最后保存失败
- 如何利用触发器报警
SET NOCOUNT ON
IF OBJECT_ID(N'tempdb..#tb') IS NOT NULL
DROP TABLE #tb
CREATE TABLE #tb(
id int IDENTITY
PRIMARY KEY,
lineID int,
state nvarchar(10),
orderid int
)
INSERT #tb(
lineID, state, orderid)
SELECT 1, N'广州东', 1 UNION ALL
SELECT 1, N'体育中心', 2 UNION ALL
SELECT 1, N'体育西', 3 UNION ALL
SELECT 1, N'烈士陵园', 4 UNION ALL
SELECT 1, N'公园前', 5 UNION ALL
SELECT 1, N'西门口', 6 UNION ALL
SELECT 2, N'火车站', 1 UNION ALL
SELECT 2, N'纪念堂', 2 UNION ALL
SELECT 2, N'公园前', 3 UNION ALL
SELECT 2, N'中大', 4 UNION ALL
SELECT 2, N'客村', 5 UNION ALL
SELECT 2, N'琶洲', 6 UNION ALL
SELECT 2, N'万胜围', 7 UNION ALL
SELECT 3, N'广州东', 1 UNION ALL
SELECT 3, N'体育西', 2 UNION ALL
SELECT 3, N'珠江新城', 3 UNION ALL
SELECT 3, N'客村', 4 UNION ALL
SELECT 3, N'市桥', 5 UNION ALL
SELECT 4, N'万胜围', 1 UNION ALL
SELECT 4, N'金洲', 2
CREATE INDEX IX_lineID
ON #tb(
lineID)
CREATE INDEX IX_state
ON #tb(
state)
CREATE INDEX IX_orderid
ON #tb(
orderid)
GO
处理方法:
之前也有发表过一些如何处理这个问题的方法,但效率不是太好。下面的这种方法加上了乘车方向的考虑:同一条线路上,只有两个乘车方向,而且一旦方向了,就不会再反向乘车(因为是从这个方向来,再坐回去是不合理的);如果某个站点可以换到另一条线路,则换乘后的另一条线路也是两个方向乘车。通过乘车方向的控制,减少了算法要搜索的路径。
-- 乘车路线查询
DECLARE
@state_start nvarchar(10),
@state_stop nvarchar(10)
SELECT
@state_start = N'广州东',
@state_stop = N'中大'
-- 查询
IF OBJECT_ID(N'tempdb..#re') IS NOT NULL
DROP TABLE #re
CREATE TABLE #re(
ID int IDENTITY
PRIMARY KEY,
path nvarchar(max),
state_count int,
line_count int,
start_lineID int,
start_state nvarchar(10),
current_lineID int,
current_state nvarchar(10),
next_orderid int,
flag int,
lineIDs varchar(max),
level int
)
CREATE INDEX IX_current_lineID
ON #re(
current_lineID )
CREATE INDEX IX_current_state
ON #re(
current_state )
CREATE INDEX IX_next_orderid
ON #re(
next_orderid )
CREATE INDEX IX_current_level
ON #re(
level )
DECLARE
@level int,
@rows int
SET
@level = 0
-- 开始
INSERT #re(
path,
state_count, line_count,
start_lineID, start_state,
current_lineID, current_state,
next_orderid, flag, lineIDs, level)
SELECT
path = CONVERT(nvarchar(max),
RTRIM(A.lineID) + N'{'
+ RTRIM(A.orderid) + N'.' + A.state
),
state_count = 0,
line_count = 0,
start_lineID = A.lineID,
start_state = A.state,
current_lineID = A.lineID,
current_state = A.state,
next_orderid = A.orderid,
flag = CASE
WHEN A.state = @state_stop THEN 0
ELSE NULL END,
lineIDs = ',' + RTRIM(A.lineID) + ',',
level = -(@level + 1)
FROM #tb A
WHERE state = @state_start
SET @rows = @@ROWCOUNT
WHILE @rows > 0
BEGIN
SELECT
@level = @level + 1
INSERT #re(
path,
state_count, line_count,
start_lineID, start_state,
current_lineID, current_state,
next_orderid, flag, lineIDs, level)
-- 同一LineID
SELECT
path = CONVERT(nvarchar(max),
A.path
+ N'->'
+ RTRIM(B.orderid) + N'.' + B.state
),
state_count = A.state_count + 1,
A.line_count,
A.start_lineID, A.start_state,
current_lineID = B.lineID,
current_state = B.state,
next_orderid = B.orderid + A.flag,
flag = CASE
WHEN B.state = @state_stop THEN 0
ELSE A.flag END,
A.lineIDs,
level = @level
FROM #re A, #tb B
WHERE A.flag <> 0
AND A.level = @level - 1
AND A.current_lineID = B.lineID
AND A.next_orderid = B.orderid
UNION ALL
-- 不同LineID
SELECT
path = CONVERT(nvarchar(max),
A.path + N')->'
+ RTRIM(B.lineID) + N'{'
+ RTRIM(B.orderid) + N'.' + B.state
),
state_count = A.state_count + 1,
line_count = A.line_count + 1,
A.start_lineID, A.start_state,
current_lineID = B.lineID,
current_state = B.state,
next_orderid = B.orderid,
flag = CASE
WHEN B.state = @state_stop THEN 0
ELSE NULL END,
A.lineIDs + RTRIM(B.lineID) + ',',
level = - @level
FROM #re A, #tb B
WHERE A.flag <> 0
AND state_count = @level - 1
AND A.current_lineID <> B.lineID
AND A.current_state = B.state
AND NOT EXISTS(
SELECT * FROM #re
WHERE CHARINDEX(',' + RTRIM(B.lineID) + ',', A.lineIDs) > 0)
SET @rows = @@ROWCOUNT
INSERT #re(
path,
state_count, line_count,
start_lineID, start_state,
current_lineID, current_state,
next_orderid, flag, lineIDs, level)
-- 不同LineID 的第站正向
SELECT
path = CONVERT(nvarchar(max),
A.path
+ N'->'
+ RTRIM(B.orderid) + N'.' + B.state
),
state_count = A.state_count + 1,
A.line_count,
A.start_lineID, A.start_state,
current_lineID = B.lineID,
current_state = B.state,
next_orderid = B.orderid + 1,
flag = CASE
WHEN B.state = @state_stop THEN 0
ELSE 1 END,
A.lineIDs,
level = @level
FROM #re A, #tb B
WHERE A.flag IS NULL
AND A.level = - @level
AND A.current_lineID = B.lineID
AND A.next_orderid + 1 = B.orderid
UNION ALL
-- 不同LineID 的第站反向
SELECT
path = CONVERT(nvarchar(max),
A.path
+ N'->'
+ RTRIM(B.orderid) + N'.' + B.state
),
state_count = A.state_count + 1,
A.line_count,
A.start_lineID, A.start_state,
current_lineID = B.lineID,
current_state = B.state,
next_orderid = B.orderid - 1,
flag = CASE
WHEN B.state = @state_stop THEN 0
ELSE - 1 END,
A.lineIDs,
level = @level
FROM #re A, #tb B
WHERE A.flag IS NULL
AND A.level = - @level
AND A.current_lineID = B.lineID
AND A.next_orderid - 1 = B.orderid
SET @rows = @rows + @@ROWCOUNT
END
SELECT
-- *,
path = path + N'}',
line_count,
state_count
FROM #re
WHERE flag = 0