将 select 与 connect by prior 从 Oracle 更改为 SQL 服务器

Change select with connect by prior from Oracle to SQL Server

你好,我在 Oracle 数据库中有这部分视图,我必须在 Microsoft Sql 服务器上更改它。

with V_LOCHIERARHY_N
(nr, nivel, location, parent, systemid, siteid, orgid, count_a, count_wo, children)
AS
SELECT     LEVEL, LPAD (' ', 2 * (LEVEL - 1)) || l.LOCATION nivel,
              LOCATION, PARENT, systemid, siteid, orgid,
             (SELECT COUNT (a.ancestor)
             FROM locancestor a
            WHERE a.LOCATION = l.LOCATION AND a.siteid = l.siteid),
                  NVL (COUNT (w.wonum), 0)
             FROM maximo.workorder w

            WHERE  (    w.reportdate >
                          TO_TIMESTAMP ('2006-06-19 00:00:01',
                                        'YYYY-MM-DD HH24:MI:SS.FF'
                                       )
                   AND w.istask = 0
                   AND w.worktype <> 'P'
                   AND w.LOCATION = l.LOCATION
                  )
              AND w.status <> 'CAN'),
          l.children
     FROM lochierarchy l
    START WITH l.LOCATION = 'StartPoint'
   CONNECT BY PRIOR l.LOCATION = l.PARENT AND l.siteid = 'SiteTest'

我需要从这个脚本中 return 给定条目的所有子项(子项的描述可以在位置 table 中找到)。

我有一个 table 的下一列:

Location Parent      Systemid Children Siteid Origid Lochierarchyid
A001     StartPoint  Primary  2        SiteTest    X      106372
A002     A001        Primary  2        SiteTest    X      105472
A003     A002        Primary  0        SiteTest    X      98654
A004     A002        Primary  1        SiteTest    X      875543
A004B    A004        Primary  0        SiteTest    X      443216
B005     StartPoint  Primary  0        SiteTest    X      544321

例如,对于给定条目 A001 将 return


A002    
 A003     
 A004
  A004B     
B005 

我在下面制作了这个视图,但我不知道如何将它与第一个集成。此外,return 我的列表也不符合正确的顺序

Parent  
 Children 1 of parent
  Children a of children 1
  children b of children 1
 children 2 of parent
  children a1 of children 2 and so on.

 WITH testCTE AS
(
     SELECT l.parent, l.location as child, l.location, l.lochierarchyid
     FROM lochierarchy l
     where location='SecondLocation' --and siteid='SiteTest'
       UNION ALL
     SELECT c.Parent, l.parent, l.location, l.lochierarchyid
     FROM lochierarchy l 
    INNER JOIN testCTE c ON l.parent = c.location
 )
  SELECT  *
  FROM testCTE c
  order BY c.parent,child asc
 ;

有人可以帮助我吗? :)

以下是使用递归查询执行此操作的方法(在 Oracle 中,这是我所知道的唯一风格)。 "The web" 报告 SQL 服务器也实现递归查询,并使用相同的语法(我相信所有这些都符合 SQL 标准,所以这并不奇怪)。试一试。

我没有创建 table,而是将所有测试数据放在第一个 CTE 中。当您尝试此解决方案时,首先删除名为 inputs 的 CTE,然后在查询的其余部分使用您实际的 table 名称。

with
     inputs ( location, parent ) as (
       select 'A001' , 'Downstream' from dual union all
       select 'A002' , 'A001'       from dual union all
       select 'A003' , 'A002'       from dual union all
       select 'A004' , 'A002'       from dual union all
       select 'A004B', 'A004'       from dual union all
       select 'B005' , 'Downstream' from dual
     ),
     r ( lvl, location ) as (
       select  1, location
         from  inputs
         where parent = 'Downstream'
       union all
       select  r.lvl + 1, i.location
         from  r join inputs i on r.location = i.parent
     )
     search depth first by lvl set ord
select lpad(' ', 2 * (lvl-1), ' ') || location as location
from   r
order by ord
;


LOCATION
--------------------
A001
  A002
    A003
    A004
      A004B
B005

6 rows selected.

ADDED:似乎 SQL 服务器没有用于递归 CTE 的 search depth/breadth first 子句(或者语法可能不同)。无论如何,这里有一个原始的 "manual" 实现:

with  (   .........   ),
     r ( lvl, location, ord ) as (
       select  1, location, location
         from  inputs
         where parent = 'Downstream'
       union all
       select  r.lvl + 1, i.location, r.location || '/' || i.location
         from  r join inputs i on r.location = i.parent
     )
select lpad(' ', 2 * (lvl-1), ' ') || location as location
from   r
order by ord
;

按照 mathguy 提出的查询,针对 MSSQL (2012) 进行了修改

    with
         inputs ( location, parent ) as (
           select 'A001' , 'StartPoint' union all
           select 'A002' , 'A001'       union all
           select 'A003' , 'A002'       union all
           select 'A004' , 'A002'       union all
       select 'A004B', 'A004'       union all
       select 'B005' , 'StartPoint' 
     ),
     r (lvl, location, ord ) as (
       select  1, location, CAST(location AS VARCHAR(400))
         from  inputs
         where parent = 'StartPoint'
       union all
       select  r.lvl + 1, i.location, CAST(r.location + '/' + i.location AS VARCHAR(400))
         from  r join inputs i on r.location = i.parent
     )
select REPLICATE(' ', 2 * (lvl-1)) + location as location
from   r
order by ord
;

输出:

location
-------------------------------------------------------------------
A001
  A002
    A003
    A004
      A004B
B005