我在sql server中有这种情况我有一个名为Room的表,这里是它的数据,我想要输出这样的图片,如图所示我试图显示我的表名为room然后在上面我已经放置了标签输入,其中包含RoomId
,ConnectingRoomID
以及更多其他列现在我想要的是一个sql select查询,它可以返回我放置标签名称输出的场景..
这些价值是自我创造的我有数以千计的房间和房间的桌子和千间连通房希望我的问题很清楚,谢谢。
答案 0 :(得分:2)
我认为你可以使用它:
with x as (
select *, sum(case connectingroomid when 0 then 1 else 0 end) over(order by roomid) as grp
from rooms
)
select x.roomid, (select min(x2.roomid) as min_roomid from x x2 where x2.grp = x.grp) as connectingroomid
from x
答案 1 :(得分:1)
这是一个递归查询:所有房间都会进入连通房,直到找到没有连通房的连接房间(即房间连接ID为0)。
with rooms (roomid, connectingroomid) as
(
select
roomid,
case when connectingroomid = 0 then
roomid
else
connectingroomid
end as connectingroomid
from room
where connectingroomid = 0
union all
select room.roomid, rooms.connectingroomid
from room
inner join rooms on room.connectingroomid = rooms.roomid
)
select * from rooms
order by connectingroomid, roomid;
这是SQL小提琴:http://www.sqlfiddle.com/#!3/46ed0/1。
编辑:这是解释。而不是在评论中这样做,我在这里做的是为了更好的可读性。WITH子句用于在此处创建递归。你看我把它命名为房间和我从房间里选择的房间。以下是阅读方法:从UNION ALL之前的部分开始。然后在UNION ALL之后递归执行该部分。因此,在UNION ALL之前,我只选择连接房间为零的记录。在您的示例中,您将显示每个房间的连接房间除了那些带有连接房间的房间,您可以自己展示房间。我在这里使用CASE来做同样的事情。但是现在我正在解释这个,我注意到,由于WHERE子句,connectroomid总是为零。因此,语句可以简化:
with rooms (roomid, connectingroomid) as
(
select
roomid,
roomid as connectingroomid
from room where connectingroomid = 0
union all
select room.roomid, rooms.connectingroomid
from room
inner join rooms on room.connectingroomid = rooms.roomid
)
select * from rooms
order by connectingroomid, roomid;
SQL小提琴:http://www.sqlfiddle.com/#!3/46ed0/2。
在UNION ALL之前的部分,我发现两个房间没有连接房间。现在,对于找到的两个房间执行UNION ALL之后的部分。它选择了刚刚找到连通房的房间。然后它选择刚刚找到连通房的房间。等等,直到联合返回不再有房间。
希望这有助于理解查询。您可以在Internet上查找“recursive cte”以查找有关该主题的更多示例和说明。
答案 2 :(得分:0)
select RoomID,
(Case when RoomID<=157 then 154
else 158 end) ConnectingRoomID
from Input
答案 3 :(得分:0)
首先,您的输出不正确:房间154也应连接到0室: - )
您所追求的是表格所定义的关系的transitive closure。使用“vanilla”SQL获取此值是impossible。但是,有一些extensions到SQL可以使recursive queries成为可能。
例如,如果我有关系“graph”:
src | target
-----+--------
1 | 2
2 | 3
3 | 4
5 | 6
6 | 7
我可以用相同的字段定义一个新表“closure”:
WITH RECURSIVE closure (src, target) AS
(SELECT src, target FROM
graph
UNION
SELECT graph.src, closure.target FROM graph, closure WHERE
graph.target = closure.src)
SELECT * FROM closure
请注意,“闭包”发生在它自己的定义中(这就是为什么这是一个递归查询)它使用原始图形作为“种子”,并通过添加距离越来越大的元组来增长(检查自己这样做)。
结果(它清楚地显示了关系如何增长):
src | target
-----+--------
1 | 2
2 | 3
3 | 4
5 | 6
6 | 7
1 | 3
2 | 4
5 | 7
1 | 4
如果您只对无法进一步扩展的对感兴趣,就像在原始示例中一样,您可以向闭包表添加一个额外的字段“distance”,并使用GROUP BY子句仅保留最大对。
免责声明:我不在Windows上,并使用了postgres。 MS SQL应该以同样的方式工作。
答案 4 :(得分:0)
尝试下面的sql:
假设@input是你的输入表
注意:我在@input表中添加了一个ID列
declare @input table
(
id int identity,
RoomId int,
ConnectingRoomId int
)
insert into @input
select 154,0 union all
select 155,154 union all
select 156,155 union all
select 157,156 union all
select 158, 0 union all
select 159, 158 union all
select 160, 159
**更新:删除联盟** SQL:
select
d.id,
d.roomId
,max(d.connectingRoomId) as ConnectingRoomId
from
(
select
bb.id,
bb.RoomId
,b.RoomId as connectingRoomId
from @input b
right join
(
select
a.id,
a.RoomId,a.ConnectingRoomId
from @input a
) bb on (b.id < bb.Id) or b.Id = bb.Id
where b.ConnectingRoomId = 0
) d
group by d.id, d.RoomId
/*
Result (OUTPUT TABLE)
id roomId ConnectingRoomId
----------- ----------- ----------------
1 154 154
2 155 154
3 156 154
4 157 154
5 158 158
6 159 158
7 160 158
*/