【问题标题】:Change select with connect by prior from Oracle to SQL Server将 select with connect by prior 从 Oracle 更改为 SQL Server
【发布时间】:2017-07-10 19:36:47
【问题描述】:

您好,我在 Oracle 数据库中有视图的这一部分,我必须在 Microsoft Sql Server 上更改它。

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'

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

我有一个包含下一列的表格:

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 将返回


A002    
 A003     
 A004
  A004B     
B005 

我在下面制作了这个视图,但我不知道如何将它与第一个集成。它也不会以正确的顺序返回我的列表

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
 ;

请有人帮助我吗? :)

【问题讨论】:

标签: sql-server oracle select sql-view connect-by


【解决方案1】:

按照 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

【讨论】:

    【解决方案2】:

    以下是使用递归查询执行此操作的方法(在 Oracle 中,这是我所知道的唯一方式)。 “网络”报告 SQL Server 也实现了递归查询,并且使用相同的语法(我相信所有这些都符合 SQL 标准,所以这并不奇怪)。试试看吧。

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

    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.
    

    添加:似乎 SQL Server 没有用于递归 CTE 的 search depth/breadth first 子句(或者语法可能不同)。无论如何,这是一个原始的“手动”实现:

    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
    ;
    

    【讨论】:

    • @AndreeaEnache - 也许 SQL Server 没有用于递归查询的 SEARCH 子句(或者语法不同)。我没有 SQL Server,但是:请在注释掉该行和最后的 ORDER BY 子句后重试。其余的工作吗?如果是这样,您可以研究 SQL Server 的 SEARCH DEPTH FIRST 等价物;我会想一下,看看我的查询中ord 的正确公式是什么(我敢肯定,Oracle 使用相同的公式来获得正确的排序)。
    • @AndreeaEnache - 好的,我添加到我的答案中:我从头开始实现了一个基本的“搜索深度优先”。
    • :-) 这就是为什么您需要了解 Oracle 和 SQL Server 的人的帮助...是的,|| 是 Oracle 中的串联,不确定 SQL Server 使用什么。对于您得到的错误:我假设它是针对 ord 的东西,并且我进一步假设您的 LOCATION 实际上不是一个字符串。正确的?如果它是一个数字,那会导致问题,因为我将它视为一个字符串,没有任何转换。如果它是一个数字,那么 ord 是锚中的一个数字,但它在递归分支中连接后变成一个字符串。如果您的位置确实是一个数字(某种 SQL Server 类型),请将其包装在 TO_CHAR() 或等效项中。
    • @AndreeaEnache - 见上文。其实你已经说是给ord了,我第一次看就错过了。
    • @AndreeaEnache - 如果您能够找到一个功能齐全的 SQL Server 解决方案,那么如果您将它发布在这里,它肯定会在未来帮助其他人。您被允许(甚至被鼓励)在 Stack Overflow 上发布您自己问题的答案,正是出于这个目的。
    猜你喜欢
    • 2018-01-24
    • 2010-10-31
    • 1970-01-01
    • 1970-01-01
    • 2011-04-25
    • 2023-03-07
    • 1970-01-01
    • 2013-10-24
    • 2016-05-22
    相关资源
    最近更新 更多