当每行包含下一行的id时,订购SQL请求
我的数据库中有两个表:当每行包含下一行的id时,订购SQL请求,sql,postgresql,request,Sql,Postgresql,Request,我的数据库中有两个表:BusLines&BusStops。总线的每个实例都可以按特定顺序有多个与之关联的站点。为了使关联更易于管理(删除或添加现有行中的新站点),关联表的结构如下所示: id_总线| id_总线站| id_下一个总线站| isFirstStop 这样做似乎是一个好主意,而不是给每一站一个数字,一旦新的站必须添加到行的开头,就必须为每一张记录更改数字(但是如果你有更好的想法,我肯定想听) 因此,重申一下:我如何在每一行上创建一个SELECT语句,以使所有停止符都按正确的顺序排列?因
BusLines
&BusStops
。总线的每个实例
都可以按特定顺序有多个与之关联的站点。为了使关联更易于管理(删除或添加现有行中的新站点),关联表的结构如下所示:
id_总线| id_总线站| id_下一个总线站| isFirstStop
这样做似乎是一个好主意,而不是给每一站一个数字,一旦新的站必须添加到行的开头,就必须为每一张记录更改数字(但是如果你有更好的想法,我肯定想听)
因此,重申一下:我如何在每一行上创建一个SELECT语句,以使所有停止符都按正确的顺序排列?因为我不能用一个简单的顺序来解决这个问题…这听起来像是一个自连接的情况,类似于:
SELECT *
FROM table a
JOIN table b
ON a.id_BusLine = b.id_Busline
AND a.id_NextBusStop = b.id_BusStop
这将它们链接在一起,但您也需要订购,如果您的isFirstStop为1/0,则:
SELECT *
FROM table a
JOIN table b
ON a.id_BusLine = b.id_Busline
AND a.id_NextBusStop = b.id_BusStop
ORDER BY isFirstStop, ....
之后需要某种方式来安排站点。这听起来像是一种自动加入的情况,类似于:
SELECT *
FROM table a
JOIN table b
ON a.id_BusLine = b.id_Busline
AND a.id_NextBusStop = b.id_BusStop
这将它们链接在一起,但您也需要订购,如果您的isFirstStop为1/0,则:
SELECT *
FROM table a
JOIN table b
ON a.id_BusLine = b.id_Busline
AND a.id_NextBusStop = b.id_BusStop
ORDER BY isFirstStop, ....
如果使用sql server,那么我认为像这样的递归cte可以工作
;WITH route AS
(
SELECT BusLineId, BusStopId, NextBusStopId
FROM BusLine_BusStop
WHERE IsFirstStop = 1
UNION ALL
SELECT b.BusLineId, b.BusStopId, b.NextBusStopId
FROM BusLine_BusStop b
INNER JOIN route r
ON r.BusLineId = b.BusLineId
AND r.NextBusStopId = b.BusStopId
WHERE IsFirstStop = 0
)
SELECT BusLineId, BusStopId
FROM route
ORDER BY BusLineId
如果使用sql server,那么我认为这样的递归cte是可行的
;WITH route AS
(
SELECT BusLineId, BusStopId, NextBusStopId
FROM BusLine_BusStop
WHERE IsFirstStop = 1
UNION ALL
SELECT b.BusLineId, b.BusStopId, b.NextBusStopId
FROM BusLine_BusStop b
INNER JOIN route r
ON r.BusLineId = b.BusLineId
AND r.NextBusStopId = b.BusStopId
WHERE IsFirstStop = 0
)
SELECT BusLineId, BusStopId
FROM route
ORDER BY BusLineId
针对SQL Server 2008-2012、PostgreSQL 9.1.9、Oracle 11g的解决方案 实际上,递归CTE是几乎所有当前RDBMS的解决方案,包括PostgreSQL(解释和示例如下所示)。但是,Oracle DBs还有另一个更好的解决方案(优化):分层查询 NOCYCLE指示Oracle返回行,即使数据中有循环 CONNECT_BY_ROOT允许您访问根元素,甚至查询中的几个层 使用HR模式: Oracle 11g的相应代码:
select
b.id_bus_line, b.id_bus_stop
from BusLine_BusStop b
start with b.is_first_stop = 1
connect by nocycle prior b.id_next_bus_stop = b.id_bus_stop and prior b.id_bus_line = b.id_bus_line
;WITH route AS
(
SELECT BusLineId, BusStopId, NextBusStopId
FROM BusLine_BusStop
WHERE IsFirstStop = 1
UNION ALL
SELECT b.BusLineId, b.BusStopId, b.NextBusStopId
FROM BusLine_BusStop b
INNER JOIN route r
ON r.BusLineId = b.BusLineId
AND r.NextBusStopId = b.BusStopId
WHERE IsFirstStop = 0 or IsFirstStop is null
)
SELECT BusLineId, BusStopId
FROM route
ORDER BY BusLineId
(我自己的代码)
请注意,标准是SQL:1999规范中的递归CTE。正如您所看到的,SQL Server和PostgreSQL之间存在一些差异
以下解决方案适用于SQL Server 2012:
select
b.id_bus_line, b.id_bus_stop
from BusLine_BusStop b
start with b.is_first_stop = 1
connect by nocycle prior b.id_next_bus_stop = b.id_bus_stop and prior b.id_bus_line = b.id_bus_line
;WITH route AS
(
SELECT BusLineId, BusStopId, NextBusStopId
FROM BusLine_BusStop
WHERE IsFirstStop = 1
UNION ALL
SELECT b.BusLineId, b.BusStopId, b.NextBusStopId
FROM BusLine_BusStop b
INNER JOIN route r
ON r.BusLineId = b.BusLineId
AND r.NextBusStopId = b.BusStopId
WHERE IsFirstStop = 0 or IsFirstStop is null
)
SELECT BusLineId, BusStopId
FROM route
ORDER BY BusLineId
(灵感来自Ti)
这是针对PostgreSQL 9.1.9的(它不是最佳的,但应该可以工作):
select
b.id_bus_line, b.id_bus_stop
from BusLine_BusStop b
start with b.is_first_stop = 1
connect by nocycle prior b.id_next_bus_stop = b.id_bus_stop and prior b.id_bus_line = b.id_bus_line
;WITH route AS
(
SELECT BusLineId, BusStopId, NextBusStopId
FROM BusLine_BusStop
WHERE IsFirstStop = 1
UNION ALL
SELECT b.BusLineId, b.BusStopId, b.NextBusStopId
FROM BusLine_BusStop b
INNER JOIN route r
ON r.BusLineId = b.BusLineId
AND r.NextBusStopId = b.BusStopId
WHERE IsFirstStop = 0 or IsFirstStop is null
)
SELECT BusLineId, BusStopId
FROM route
ORDER BY BusLineId
诀窍在于为当前会话创建一个可重置的专用临时序列
create temp sequence rownum;
WITH final_route AS
(
WITH RECURSIVE route AS
(
SELECT BusLineId, BusStopId, NextBusStopId
FROM BusLine_BusStop
WHERE IsFirstStop = 1
UNION ALL
SELECT b.BusLineId, b.BusStopId, b.NextBusStopId
FROM BusLine_BusStop b
INNER JOIN route r
ON r.BusLineId = b.BusLineId
AND r.NextBusStopId = b.BusStopId
WHERE IsFirstStop = 0 or IsFirstStop is null
)
SELECT BusLineId, BusStopId, nextval('rownum') as rownum
FROM route
)
SELECT BusLineId, BusStopId
FROM final_route
ORDER BY BusLineId, rownum;
我自己的
编辑:
select
b.id_bus_line, b.id_bus_stop
from BusLine_BusStop b
start with b.is_first_stop = 1
connect by nocycle prior b.id_next_bus_stop = b.id_bus_stop and prior b.id_bus_line = b.id_bus_line
;WITH route AS
(
SELECT BusLineId, BusStopId, NextBusStopId
FROM BusLine_BusStop
WHERE IsFirstStop = 1
UNION ALL
SELECT b.BusLineId, b.BusStopId, b.NextBusStopId
FROM BusLine_BusStop b
INNER JOIN route r
ON r.BusLineId = b.BusLineId
AND r.NextBusStopId = b.BusStopId
WHERE IsFirstStop = 0 or IsFirstStop is null
)
SELECT BusLineId, BusStopId
FROM route
ORDER BY BusLineId
抱歉进行了多次编辑。通过子记录而不是父记录连接记录是很少见的。
您可以通过删除isFirstStop列并使用id_PreviousBusStop列(如果可能)连接记录来避免这种糟糕的表示。在这种情况下,必须为第一条记录将id_PreviousBusStop设置为null。
您可以节省空间(对于固定长度的数据,整个空间仍保留)。此外,使用更少的字符,您的查询将更加高效。SQL Server 2008-2012解决方案、PostgreSQL 9.1.9、Oracle 11g 实际上,递归CTE是几乎所有当前RDBMS的解决方案,包括PostgreSQL(解释和示例如下所示)。但是,Oracle DBs还有另一个更好的解决方案(优化):分层查询 NOCYCLE指示Oracle返回行,即使数据中有循环 CONNECT_BY_ROOT允许您访问根元素,甚至查询中的几个层 使用HR模式: Oracle 11g的相应代码:
select
b.id_bus_line, b.id_bus_stop
from BusLine_BusStop b
start with b.is_first_stop = 1
connect by nocycle prior b.id_next_bus_stop = b.id_bus_stop and prior b.id_bus_line = b.id_bus_line
;WITH route AS
(
SELECT BusLineId, BusStopId, NextBusStopId
FROM BusLine_BusStop
WHERE IsFirstStop = 1
UNION ALL
SELECT b.BusLineId, b.BusStopId, b.NextBusStopId
FROM BusLine_BusStop b
INNER JOIN route r
ON r.BusLineId = b.BusLineId
AND r.NextBusStopId = b.BusStopId
WHERE IsFirstStop = 0 or IsFirstStop is null
)
SELECT BusLineId, BusStopId
FROM route
ORDER BY BusLineId
(我自己的代码)
请注意,标准是SQL:1999规范中的递归CTE。正如您所看到的,SQL Server和PostgreSQL之间存在一些差异
以下解决方案适用于SQL Server 2012:
select
b.id_bus_line, b.id_bus_stop
from BusLine_BusStop b
start with b.is_first_stop = 1
connect by nocycle prior b.id_next_bus_stop = b.id_bus_stop and prior b.id_bus_line = b.id_bus_line
;WITH route AS
(
SELECT BusLineId, BusStopId, NextBusStopId
FROM BusLine_BusStop
WHERE IsFirstStop = 1
UNION ALL
SELECT b.BusLineId, b.BusStopId, b.NextBusStopId
FROM BusLine_BusStop b
INNER JOIN route r
ON r.BusLineId = b.BusLineId
AND r.NextBusStopId = b.BusStopId
WHERE IsFirstStop = 0 or IsFirstStop is null
)
SELECT BusLineId, BusStopId
FROM route
ORDER BY BusLineId
(灵感来自Ti)
这是针对PostgreSQL 9.1.9的(它不是最佳的,但应该可以工作):
select
b.id_bus_line, b.id_bus_stop
from BusLine_BusStop b
start with b.is_first_stop = 1
connect by nocycle prior b.id_next_bus_stop = b.id_bus_stop and prior b.id_bus_line = b.id_bus_line
;WITH route AS
(
SELECT BusLineId, BusStopId, NextBusStopId
FROM BusLine_BusStop
WHERE IsFirstStop = 1
UNION ALL
SELECT b.BusLineId, b.BusStopId, b.NextBusStopId
FROM BusLine_BusStop b
INNER JOIN route r
ON r.BusLineId = b.BusLineId
AND r.NextBusStopId = b.BusStopId
WHERE IsFirstStop = 0 or IsFirstStop is null
)
SELECT BusLineId, BusStopId
FROM route
ORDER BY BusLineId
诀窍在于为当前会话创建一个可重置的专用临时序列
create temp sequence rownum;
WITH final_route AS
(
WITH RECURSIVE route AS
(
SELECT BusLineId, BusStopId, NextBusStopId
FROM BusLine_BusStop
WHERE IsFirstStop = 1
UNION ALL
SELECT b.BusLineId, b.BusStopId, b.NextBusStopId
FROM BusLine_BusStop b
INNER JOIN route r
ON r.BusLineId = b.BusLineId
AND r.NextBusStopId = b.BusStopId
WHERE IsFirstStop = 0 or IsFirstStop is null
)
SELECT BusLineId, BusStopId, nextval('rownum') as rownum
FROM route
)
SELECT BusLineId, BusStopId
FROM final_route
ORDER BY BusLineId, rownum;
我自己的
编辑:
select
b.id_bus_line, b.id_bus_stop
from BusLine_BusStop b
start with b.is_first_stop = 1
connect by nocycle prior b.id_next_bus_stop = b.id_bus_stop and prior b.id_bus_line = b.id_bus_line
;WITH route AS
(
SELECT BusLineId, BusStopId, NextBusStopId
FROM BusLine_BusStop
WHERE IsFirstStop = 1
UNION ALL
SELECT b.BusLineId, b.BusStopId, b.NextBusStopId
FROM BusLine_BusStop b
INNER JOIN route r
ON r.BusLineId = b.BusLineId
AND r.NextBusStopId = b.BusStopId
WHERE IsFirstStop = 0 or IsFirstStop is null
)
SELECT BusLineId, BusStopId
FROM route
ORDER BY BusLineId
抱歉进行了多次编辑。通过子记录而不是父记录连接记录是很少见的。
您可以通过删除isFirstStop列并使用id_PreviousBusStop列(如果可能)连接记录来避免这种糟糕的表示。在这种情况下,必须为第一条记录将id_PreviousBusStop设置为null。
您可以节省空间(对于固定长度的数据,整个空间仍保留)。此外,使用更少的字符,您的查询将变得更加高效。精细SQL方法的另一种替代方法是复制以10为单位指定行号的旧基本技巧,这样您仍然可以在现有行号之间插入新的行号——如果您需要使用整数的话 当然,如果您愿意,您可以以1000为增量进行编号。如果你喜欢事物整洁,你可以周期性地运行一个重新编号的程序来平衡数字
低技术,可以在任何数据库上运行,简单的order by方法将优于所有其他方法。精细SQL方法的替代方法是复制以10为单位指定行号的旧基本技巧,以便在现有行号之间仍然可以插入新的行号——如果需要使用整数的话 当然,如果您愿意,您可以以1000为增量进行编号。如果你喜欢事物整洁,你可以周期性地运行一个重新编号的程序来平衡数字 低技术,可用于任何数据库,简单的order by将优于所有其他方法。当前设计 坐在这张桌子上
CREATE TEMP TABLE bus_lnk(
id_busline integer
,id_busstop integer
,id_nextbusstop integer
,isfirststop boolean
);
该查询包括每条线路每站的运行编号,应该比wha更简单、更快