Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
当每行包含下一行的id时,订购SQL请求_Sql_Postgresql_Request - Fatal编程技术网

当每行包含下一行的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更简单、更快