【问题标题】:SYS_CONNECT_BY_PATH in SQL ServerSQL Server 中的 SYS_CONNECT_BY_PATH
【发布时间】:2012-10-09 21:51:06
【问题描述】:

我正在做一个迁移项目,需要将以下 Oracle 查询转换为它的 SQL Server 等效查询。

select SYS_CONNECT_BY_PATH (b.actionnr,'/') as FATHER, SYS_CONNECT_BY_PATH (b.actionnr,'     | ') as REFPATH, LEVEL, 
(select count(p.refactionnr) from zisjob.zj_action p where p.refactionnr=b.actionnr)
Childs, b.* from 
( select NVL(x.ANZFiles,0) ANZFiles, act.actionnr, act.refactionnr, act.lfno, act.jobnr,     act."TYPE", act.actiontype
from zisjob.zj_action act, zisjob.zj_actiontype t, 
( select f.lno, count(f.filenr) as ANZFiles from zisjob.zj_file f where f.lno != f.lfno     Group by f.lno )x
where act.lfno=10 and act.actiontype = t.typeid(+) and act.actionnr = x.lno(+) )
b start with b.actionnr in 
(select b.actionnr from zisjob.zj_action b where b.lfno = 10 and b.refactionnr is    null)
connect by nocycle prior b.actionnr=b.refactionnr order by 1 desc, 2 asc

我正在使用 CTE 来执行此操作。到目前为止,我想出了以下几点:

with h$cte as 
(
   select
      cast (convert(varchar,b.actionnr)+'/' as varchar(max)) as FATHER,
      cast(convert(varchar,b.actionnr)+' | ' as varchar(max)) as REFPATH,
      1 as LEVEL,
      --cast (row_number() over (order by @@spid) as varchar(max)) as LEVEL,
      (select count(p.refactionnr) from zisjob.zj_action p 
       where p.refactionnr = b.actionnr) Childs, 
      b.* 
   from
     (select 
         isnull(x.ANZFiles, 0) ANZFiles, act.actionnr, act.refactionnr, act.lfno,  
         act.jobnr, act."TYPE", act.actiontype
      from zisjob.zj_action act 
      left outer join zisjob.zj_actiontype t on act.actiontype = t.typeid 
      left outer join
          (select f.lno, count(f.filenr) as ANZFiles 
           from zisjob.zj_file f
           where f.lno != f.lfno Group by f.lno ) x on act.actionnr = x.lno
      where act.lfno = 10) b
where 
   b.actionnr in
       (select b.actionnr from zisjob.zj_action b 
        where b.lfno = 10 and b.refactionnr is null)

UNION ALL

select
    CAST(FATHER + '/'+ b.ACTIONNR as varchar(max)) as FATHER,
    CAST(REFPATH + '|'+b.ACTIONNR AS VARCHAR(MAX)) as REFPATH,
    h$cte.LEVEL + 1 as LEVEL,
    (select count(p.refactionnr) from zisjob.zj_action p  
     where p.refactionnr = b.actionnr) Childs, 
    b.*
from
   (select isnull(x.ANZFiles, 0) ANZFiles, act.actionnr, act.refactionnr, 
           act.lfno, act.jobnr, act."TYPE", act.actiontype
    from zisjob.zj_action act 
    left outer join zisjob.zj_actiontype t on act.actiontype = t.typeid 
    left outer join
        (select f.lno, count(f.filenr) as ANZFiles from zisjob.zj_file f
         where f.lno != f.lfno Group by f.lno) x on act.actionnr = x.lno
    where act.lfno = 10) b, 
    h$cte
where 
    b.actionnr in
        (select b.actionnr from zisjob.zj_action b 
         where b.lfno = 10 and b.refactionnr is null)
    and h$cte.ACTIONNR = h$cte.REFACTIONNR
)
select <columns> from h$cte

翻译后的查询出现以下错误:

消息 467,第 16 级,状态 1,第 1 行
在递归公用表表达式 'h 的递归部分中不允许使用 GROUP BY、HAVING 或聚合函数$cte'。

消息 462,第 16 级,状态 1,第 1 行
递归公用表表达式“h$cte”的递归部分不允许外连接

我该如何解决这个问题?非常感谢任何形式的帮助。提前致谢。

【问题讨论】:

    标签: sql oracle sql-server-2008 recursion common-table-expression


    【解决方案1】:

    我终于解决了这个问题:

    WITH dummy AS(
    
    select isnull(x.ANZFiles,0) ANZFiles, act.actionnr, act.refactionnr, act.lfno, act.jobnr, act."TYPE", act.actiontype
    
    from zisjob.zj_action act left outer join zisjob.zj_actiontype t on act.actiontype = t.typeid left outer join 
    
    ( select f.lno, count(f.filenr) as ANZFiles from zisjob.zj_file f 
    
    where f.lno != f.lfno Group by f.lno )x on act.actionnr = x.lno
    
    where act.lfno=10), 
    
     dummy2 as(
    
    select count(p.refactionnr) as Childs 
    
    from zisjob.zj_action p inner join dummy b on p.refactionnr=b.actionnr
    
    ),
    
    h$cte as(
    
    select 
    
    cast ('/'+convert(varchar,b.actionnr) as varchar(max)) as FATHER, 
    
    cast(' | '+convert(varchar,b.actionnr) as varchar(max)) as REFPATH, 
    
    1 as LEVEL,
    
    c.Childs,
    
    --cast (row_number() over (order by @@spid) as varchar(max)) as LEVEL, 
    
    b.* 
    
    from dummy b, dummy2 c
    
    where b.actionnr in 
    
    (select b.actionnr from zisjob.zj_action b where b.lfno = 10 and b.refactionnr is null)
    
    UNION ALL
    
    select
    
    CAST(FATHER + '/'+ b.ACTIONNR as varchar(max)) as FATHER,
    
    CAST(REFPATH + '|'+b.ACTIONNR AS VARCHAR(MAX)) as REFPATH,
    
    h$cte.LEVEL + 1 as LEVEL,c.Childs,
    
    b.*
    
    from dummy b, dummy2 c, h$cte
    
    where b.actionnr in 
    
    (select b.actionnr from zisjob.zj_action b where b.lfno = 10 and b.refactionnr is null)
    
    and h$cte.ACTIONNR = h$cte.REFACTIONNR
    
    )
    
    select * from h$cte
    

    由于不允许我在 CTE 的递归成员中编写外连接和 GROUP BY、HAVING 或聚合函数,因此我将其移到了新的 CTE 下。这就像一个魅力。

    干杯!!!

    【讨论】:

      【解决方案2】:

      我已经通过创建数据库函数解决了这个问题

      创建一个类似 "ufn_GetParentPath" 的函数,使用它代替 "SYS_CONNECT_BY_PATH" 传递 ID 作为参数。

      CREATE FUNCTION [dbo].[ufn_GetParentPath] ( @pCurrentNodeID    INT )
      RETURNS VARCHAR(1000)
      AS
      BEGIN
      
      DECLARE @vCurrentNodeName     VARCHAR(50)
      DECLARE @vParentID            INT
      
      IF @pCurrentNodeID IS NULL OR @pCurrentNodeID = 0
          RETURN NULL
      
      SELECT @vCurrentNodeName = [Name], @vParentID = [ParentID]
      FROM [dbo].[Hierarchy]
      WHERE [ID] = @pCurrentNodeID
      
      RETURN ISNULL([dbo].[ufn_GetParentPath] ( @vParentID ) + '/', '') + @vCurrentNodeName
      
      END
      GO
      

      【讨论】:

        猜你喜欢
        • 2014-11-24
        • 2017-10-07
        • 2015-07-25
        • 2021-05-13
        • 1970-01-01
        • 1970-01-01
        • 2015-09-27
        • 1970-01-01
        • 2010-10-23
        相关资源
        最近更新 更多