mssql

推荐列表 站点导航

当前位置:首页 > 数据库 > mssql >

在SQL Server中实现最短路径搜索的解决方法

来源:网络整理  作者:网络  发布时间:2020-12-13 00:24
本篇文章小编为大家介绍,在SQL Server中实现最短路径搜索的解决方法。需要的朋友参考下...
@Node nvarchar(50),
在接下来,我就描述在SQL Server中,如何实现。当然我这里采用的前面说的第2种方法,以"P"和"J"为始点像中心外层层扩展。


第1方法是,

use TestDB
select * Into #Path2 from cte_path2
图3.

('o','i'),('o','l')

('a','b'),('a','c'),('a','d'),('a','e'),

在SQL Server中实现最短路径搜索的解决方法

select RelatedNode, Node, @level from RelationGraph a where a.RelatedNode = @Node --反向:以@Node作为目标进行查询

复制代码 代码如下:

Not exists(select 1 from #1 where Node=a.Node)

where exists(select 1 from #2 where RelatedNode=a.Node And Level=@level) And
)

go
--下面是构造返回的结果路径
return

从上面可以看出第2种可能路径,经过的节点最少。

Node nvarchar(50),--相对源点
--
go



select Node, RelatedNode, @level from RelationGraph a where a.Node =@RelatedNode union --正向:以@RelatedNode作为源查询
if @RelatedNode_WhileFlag >0
From #Path1 a
and b.Level=a.Level-1

了能够更好的描述表RelationGraph中字段Node和 RelatedNode的关系,我在这里特意使用一个图形来描述,
From RelationGraph a
union all

('c','i'),('c','j'),

end
(
select distinct RelationGraphPath,StopCount From cte_result where Result_row=1

复制代码 代码如下:


解析:

图2.

end
如图2.

create table RelactionGraph(ID int identity,Item nvarchar(50),RelactionItem nvarchar(20),constraint PK_RelactionGraph primary key(ID))

;with cte_result As
where exists(select 1 from #2 where RelatedNode=a.RelatedNode And Level=@level) And
While_Out:

if not exists(select 1 from #1) or not exists(select 1 from #2)
--如果直接找到两个Node存在直接关系就直接返回

('f','k'),('f','l'),


end
set nocount on
(
And @level<@MaxLevel --控制深度

and b.Level=a.Level-1

在图2,可清晰的看出各个节点直接如何相连,也可以清楚的看出节点"p"至节点"j"的的几种可能路径。

from cte_path1 a
select b.Node,a.RelatedNode,b.Level,convert(nvarchar(2000),b.Node+' -> '+a.RelationGraphPath) As RelationGraphPath ,Convert(smallint,a.PathLevel+1) As PathLevel
goto While_Out
)

Not exists(select 1 from #2 where Node=a.Node)
end

在SQL Server中实现最短路径搜索的解决方法

select Node, RelatedNode, @level from RelationGraph a where a.Node =@Node union --正向:以@Node作为源查询

图1.
begin
insert into #2 ( Node, RelatedNode, Level )
inner join #2 b on b.RelatedNode=a.Node
go
select a.Node,a.RelatedNode,Level,convert(nvarchar(2000),a.Node+' -> '+a.RelatedNode) As RelationGraphPath,Convert(smallint,1) As PathLevel From #1 a where exists(select 1 from #2 where RelatedNode=a.RelatedNode)

复制代码 代码如下:

在SQL Server中实现最短路径搜索的解决方法

--正向
declare
if Exists(select 1 from RelationGraph where (Node=@Node And RelatedNode=@RelatedNode) or (Node=@RelatedNode And RelatedNode=@Node) ) or @Node=@RelatedNode
RelatedNode nvarchar(50), --相对目标

create proc up_GetPath
--反向
这是去年的问题了,今天在整理邮件的时候才发现这个问题,感觉顶有意思的,特记录下来。

@Node_WhileFlag bit=1, --以@Node作为中心进行搜索时候,作为能否循环搜索的标记
set @RelatedNode_WhileFlag=sign(@@rowcount)

('b','f'),('b','g'),('b','h'),

)
Drop proc up_GetPath

create nonclustered index IX_RelactionGraph_Item on RelactionGraph(Item) include(RelactionItem)

begin
if object_id('tempdb..#2') Is not null Drop Table #2 --临时表#2,存储的是以@RelatedNode作为中心向外扩展的各节点数据
)
if @Node_WhileFlag >0
select b.Node,a.RelatedNode,b.Level,convert(nvarchar(2000),a.RelationGraphPath+' -> '+b.Node) As RelationGraphPath ,Convert(smallint,a.PathLevel+1)
select a.RelatedNode,a.Node,@level+1


select convert(nvarchar(2000),@Node + ' --> '+ @RelatedNode) As RelationGraphPath,convert(smallint,0) As StopCount
while not exists(select 1 from #1 a inner join #2 b on b.RelatedNode=a.RelatedNode) --判断是否出现切点

insert into #1 ( Node, RelatedNode, Level )

if object_id('tempdb..#1') Is not null Drop Table #1 --临时表#1,存储的是以@Node作为中心向外扩展的各节点数据
;with cte_path2 As
where a.Level=1
if object_id('tempdb..#Path1') Is not null Drop Table #Path1
inner join #Path2 b on b.RelatedNode=a.RelatedNode

go
where exists(select 1 from #1 where RelatedNode=a.RelatedNode And Level=@level) And
As

From RelationGraph a
end
select * Into #Path1 from cte_path1
if object_id('tempdb..#Path2') Is not null Drop Table #Path2
if object_id('up_GetPath') Is not null
Level smallint --深度

在表RelationGraph中,有三个字段(ID,Node,RelatedNode),其中Node和RelatedNode两个字段描述两个节点的连接关系;现在要求,找出从节点"p"至节点"j",最短路径(即经过的节点最少)。


select RelatedNode, Node, @level from RelationGraph a where a.RelatedNode = @RelatedNode --反向:以@RelatedNode作为目标进行查询
--如果在表RelationGraph中找不到@Node 或 @RelatedNode 数据,就直接跳过后面的While过程
insert into #1 ( Node, RelatedNode, Level )

create nonclustered index IX_RelactionGraph_RelactionItem on RelactionGraph(RelactionItem) include(Item)

开始

为了解决开始的问题,我参考了两种方法,

@RelatedNode_WhileFlag bit=1 --以@RelatedNode作为中心进行搜索时候,作为能否循环搜索的标记
select a.RelationGraphPath+' -> '+b.RelationGraphPath As RelationGraphPath,a.PathLevel+b.PathLevel -1 As StopCount,rank() over(order by a.PathLevel+b.PathLevel) As Result_row

下面是存储过程的执行:

select @level+=1
--反向

('k','o'),('k','p'),

在SQL Server中实现最短路径搜索的解决方法

select a.Node,a.RelatedNode,Level,convert(nvarchar(2000),a.Node) As RelationGraphPath,Convert(smallint,1) As PathLevel From #2 a where exists(select 1 from #1 where RelatedNode=a.RelatedNode)

inner join #1 b on b.RelatedNode=a.Node
union
Not exists(select 1 from #1 where Node=a.RelatedNode)
begin

第2方法是,

set @RelatedNode_WhileFlag=sign(@@rowcount)

insert into RelactionGraph (Item, RelactionItem ) values

use TestDB


针对第1种方法的改进,就是采用多源点方法,这里就是以节点"p"和节点"j"为中心向外层扩展,直到两圆外切点,如图4. :

--Procedure:
select a.Node,a.RelatedNode,@level+1
@level smallint =1, --当前搜索的深度
union all
select a.Node,a.RelatedNode,@level+1
--正向
@MaxLevel smallint=100, --最大可搜索深度

go

go

go


create table #2(Node nvarchar(50),RelatedNode nvarchar(50),Level smallint)
上面的存储过程,主要分为两大部分,第1部分是实现如何搜索,第2部分实现如何构造返回结果。其中第1部分的代码根据前面的方法2,通过@Node 和 @RelatedNode 两个节点向外层搜索,每次搜索返回的节点都保存至临时表#1和#2,再判断临时表#1和#2有没有出现切点,如果出现就说明已找到最短的路径(经过多节点数最少),否则就继续循环搜索,直到循环至最大的搜索深度(@MaxLevel smallint=100)或找到切点。要是到100层都没搜索到切点,将放弃搜索。这里使用最大可搜索深度@MaxLevel,目的是控制由于数据量大可能会导致性能差,因为在这里数据量与搜索性能成反比。代码中还说到一个正向和反向搜索,主要是相对Node 和 RelatedNode来说,它们两者互为参照对象,进行向外搜索使用。

set @Node_WhileFlag=sign(@@rowcount)
insert into #2 ( Node, RelatedNode, Level )

Not exists(select 1 from #2 where Node=a.RelatedNode)

;with cte_path1 As
编写一个存储过程up_GetPath
实现:
union
where exists(select 1 from #1 where RelatedNode=a.Node And Level=@level) And

图4.

if object_id('RelactionGraph') Is not null drop table RelactionGraph

(
From RelationGraph a

参考单源最短路径算法:


)
From RelationGraph a
set @Node_WhileFlag=sign(@@rowcount)

在SQL Server中实现最短路径搜索的解决方法


@RelatedNode nvarchar(50)
create table #1(

这里提供有表RelactionGraph的create& Insert数据的脚本:
(
select a.RelatedNode,a.Node,@level+1


and b.Level=1
begin
from cte_path2 a
and (@Node_WhileFlag|@RelatedNode_WhileFlag)>0 --判断是否能搜索


begin

相关热词: 方法 解决

本站内容来源于网络,如有侵权请与我们联系,我们会及时删除,我们深感抱歉!
注:本站所有信息仅供用于网络技术学习参考,学习中请遵循相关法律法规!

本文地址: https://www.juheyunku.com/sql/mssql/3115.shtml

最新文章
sql server 关于设置null的一 sql server 关于设置null的一

时间:2020-12-28

详解SQL游标的用法 详解SQL游标的用法

时间:2020-12-27

vs code连接sql server数据库步 vs code连接sql server数据库步

时间:2020-12-27

图书管理系统的sqlserver数 图书管理系统的sqlserver数

时间:2020-12-25

详解SQL 通配符 详解SQL 通配符

时间:2020-12-25

sql四大排名函数之ROW_NUM sql四大排名函数之ROW_NUM

时间:2020-12-25

SQLServer数据库处于恢复挂 SQLServer数据库处于恢复挂

时间:2020-12-24

Win10 64位安装个人版SQL20 Win10 64位安装个人版SQL20

时间:2020-12-24

Copyright © www.juheyunku.com      关于 | 合作 | 声明 | 联系 | 更新 | 地图 | Tags

在SQL Server中实现最短路径搜索的解决方法

2020-12-13 编辑:网络

@Node nvarchar(50),
在接下来,我就描述在SQL Server中,如何实现。当然我这里采用的前面说的第2种方法,以"P"和"J"为始点像中心外层层扩展。


第1方法是,

use TestDB
select * Into #Path2 from cte_path2
图3.

('o','i'),('o','l')

('a','b'),('a','c'),('a','d'),('a','e'),

在SQL Server中实现最短路径搜索的解决方法

select RelatedNode, Node, @level from RelationGraph a where a.RelatedNode = @Node --反向:以@Node作为目标进行查询

复制代码 代码如下:

Not exists(select 1 from #1 where Node=a.Node)

where exists(select 1 from #2 where RelatedNode=a.Node And Level=@level) And
)

go
--下面是构造返回的结果路径
return

从上面可以看出第2种可能路径,经过的节点最少。

Node nvarchar(50),--相对源点
--
go



select Node, RelatedNode, @level from RelationGraph a where a.Node =@RelatedNode union --正向:以@RelatedNode作为源查询
if @RelatedNode_WhileFlag >0
From #Path1 a
and b.Level=a.Level-1

了能够更好的描述表RelationGraph中字段Node和 RelatedNode的关系,我在这里特意使用一个图形来描述,
From RelationGraph a
union all

('c','i'),('c','j'),

end
(
select distinct RelationGraphPath,StopCount From cte_result where Result_row=1

复制代码 代码如下:


解析:

图2.

end
如图2.

create table RelactionGraph(ID int identity,Item nvarchar(50),RelactionItem nvarchar(20),constraint PK_RelactionGraph primary key(ID))

;with cte_result As
where exists(select 1 from #2 where RelatedNode=a.RelatedNode And Level=@level) And
While_Out:

if not exists(select 1 from #1) or not exists(select 1 from #2)
--如果直接找到两个Node存在直接关系就直接返回

('f','k'),('f','l'),


end
set nocount on
(
And @level<@MaxLevel --控制深度

and b.Level=a.Level-1

在图2,可清晰的看出各个节点直接如何相连,也可以清楚的看出节点"p"至节点"j"的的几种可能路径。

from cte_path1 a
select b.Node,a.RelatedNode,b.Level,convert(nvarchar(2000),b.Node+' -> '+a.RelationGraphPath) As RelationGraphPath ,Convert(smallint,a.PathLevel+1) As PathLevel
goto While_Out
)

Not exists(select 1 from #2 where Node=a.Node)
end

在SQL Server中实现最短路径搜索的解决方法

select Node, RelatedNode, @level from RelationGraph a where a.Node =@Node union --正向:以@Node作为源查询

图1.
begin
insert into #2 ( Node, RelatedNode, Level )
inner join #2 b on b.RelatedNode=a.Node
go
select a.Node,a.RelatedNode,Level,convert(nvarchar(2000),a.Node+' -> '+a.RelatedNode) As RelationGraphPath,Convert(smallint,1) As PathLevel From #1 a where exists(select 1 from #2 where RelatedNode=a.RelatedNode)

复制代码 代码如下:

在SQL Server中实现最短路径搜索的解决方法

--正向
declare
if Exists(select 1 from RelationGraph where (Node=@Node And RelatedNode=@RelatedNode) or (Node=@RelatedNode And RelatedNode=@Node) ) or @Node=@RelatedNode
RelatedNode nvarchar(50), --相对目标

create proc up_GetPath
--反向
这是去年的问题了,今天在整理邮件的时候才发现这个问题,感觉顶有意思的,特记录下来。

@Node_WhileFlag bit=1, --以@Node作为中心进行搜索时候,作为能否循环搜索的标记
set @RelatedNode_WhileFlag=sign(@@rowcount)

('b','f'),('b','g'),('b','h'),

)
Drop proc up_GetPath

create nonclustered index IX_RelactionGraph_Item on RelactionGraph(Item) include(RelactionItem)

begin
if object_id('tempdb..#2') Is not null Drop Table #2 --临时表#2,存储的是以@RelatedNode作为中心向外扩展的各节点数据
)
if @Node_WhileFlag >0
select b.Node,a.RelatedNode,b.Level,convert(nvarchar(2000),a.RelationGraphPath+' -> '+b.Node) As RelationGraphPath ,Convert(smallint,a.PathLevel+1)
select a.RelatedNode,a.Node,@level+1


select convert(nvarchar(2000),@Node + ' --> '+ @RelatedNode) As RelationGraphPath,convert(smallint,0) As StopCount
while not exists(select 1 from #1 a inner join #2 b on b.RelatedNode=a.RelatedNode) --判断是否出现切点

insert into #1 ( Node, RelatedNode, Level )

if object_id('tempdb..#1') Is not null Drop Table #1 --临时表#1,存储的是以@Node作为中心向外扩展的各节点数据
;with cte_path2 As
where a.Level=1
if object_id('tempdb..#Path1') Is not null Drop Table #Path1
inner join #Path2 b on b.RelatedNode=a.RelatedNode

go
where exists(select 1 from #1 where RelatedNode=a.RelatedNode And Level=@level) And
As

From RelationGraph a
end
select * Into #Path1 from cte_path1
if object_id('tempdb..#Path2') Is not null Drop Table #Path2
if object_id('up_GetPath') Is not null
Level smallint --深度

在表RelationGraph中,有三个字段(ID,Node,RelatedNode),其中Node和RelatedNode两个字段描述两个节点的连接关系;现在要求,找出从节点"p"至节点"j",最短路径(即经过的节点最少)。


select RelatedNode, Node, @level from RelationGraph a where a.RelatedNode = @RelatedNode --反向:以@RelatedNode作为目标进行查询
--如果在表RelationGraph中找不到@Node 或 @RelatedNode 数据,就直接跳过后面的While过程
insert into #1 ( Node, RelatedNode, Level )

create nonclustered index IX_RelactionGraph_RelactionItem on RelactionGraph(RelactionItem) include(Item)

开始

为了解决开始的问题,我参考了两种方法,

@RelatedNode_WhileFlag bit=1 --以@RelatedNode作为中心进行搜索时候,作为能否循环搜索的标记
select a.RelationGraphPath+' -> '+b.RelationGraphPath As RelationGraphPath,a.PathLevel+b.PathLevel -1 As StopCount,rank() over(order by a.PathLevel+b.PathLevel) As Result_row

下面是存储过程的执行:

select @level+=1
--反向

('k','o'),('k','p'),

在SQL Server中实现最短路径搜索的解决方法

select a.Node,a.RelatedNode,Level,convert(nvarchar(2000),a.Node) As RelationGraphPath,Convert(smallint,1) As PathLevel From #2 a where exists(select 1 from #1 where RelatedNode=a.RelatedNode)

inner join #1 b on b.RelatedNode=a.Node
union
Not exists(select 1 from #1 where Node=a.RelatedNode)
begin

第2方法是,

set @RelatedNode_WhileFlag=sign(@@rowcount)

insert into RelactionGraph (Item, RelactionItem ) values

use TestDB


针对第1种方法的改进,就是采用多源点方法,这里就是以节点"p"和节点"j"为中心向外层扩展,直到两圆外切点,如图4. :

--Procedure:
select a.Node,a.RelatedNode,@level+1
@level smallint =1, --当前搜索的深度
union all
select a.Node,a.RelatedNode,@level+1
--正向
@MaxLevel smallint=100, --最大可搜索深度

go

go

go


create table #2(Node nvarchar(50),RelatedNode nvarchar(50),Level smallint)
上面的存储过程,主要分为两大部分,第1部分是实现如何搜索,第2部分实现如何构造返回结果。其中第1部分的代码根据前面的方法2,通过@Node 和 @RelatedNode 两个节点向外层搜索,每次搜索返回的节点都保存至临时表#1和#2,再判断临时表#1和#2有没有出现切点,如果出现就说明已找到最短的路径(经过多节点数最少),否则就继续循环搜索,直到循环至最大的搜索深度(@MaxLevel smallint=100)或找到切点。要是到100层都没搜索到切点,将放弃搜索。这里使用最大可搜索深度@MaxLevel,目的是控制由于数据量大可能会导致性能差,因为在这里数据量与搜索性能成反比。代码中还说到一个正向和反向搜索,主要是相对Node 和 RelatedNode来说,它们两者互为参照对象,进行向外搜索使用。

set @Node_WhileFlag=sign(@@rowcount)
insert into #2 ( Node, RelatedNode, Level )

Not exists(select 1 from #2 where Node=a.RelatedNode)

;with cte_path1 As
编写一个存储过程up_GetPath
实现:
union
where exists(select 1 from #1 where RelatedNode=a.Node And Level=@level) And

图4.

if object_id('RelactionGraph') Is not null drop table RelactionGraph

(
From RelationGraph a

参考单源最短路径算法:


)
From RelationGraph a
set @Node_WhileFlag=sign(@@rowcount)

在SQL Server中实现最短路径搜索的解决方法


@RelatedNode nvarchar(50)
create table #1(

这里提供有表RelactionGraph的create& Insert数据的脚本:
(
select a.RelatedNode,a.Node,@level+1


and b.Level=1
begin
from cte_path2 a
and (@Node_WhileFlag|@RelatedNode_WhileFlag)>0 --判断是否能搜索


begin

本站内容来源于网络,如有侵权请与我们联系,我们会及时删除,我们深感抱歉!
注:本站所有信息仅供学习参考!
本文地址为 https://www.juheyunku.com/sql/mssql/3115.shtml

相关文章

风云图片

推荐阅读

返回mssql频道首页