/ / SQL ServerのSYS_CONNECT_BY_PATH-sql、oracle、sql-server-2008、recursion、common-table-expression

SQL ServerのSYS_CONNECT_BY_PATH-sql、oracle、sql-server-2008、recursion、common-table-expression

私は移行プロジェクトに取り組んでおり、次の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
GROUP BY、HAVING、または集約関数は、再帰共通テーブル式「h $ cte」の再帰部分では許可されていません。

メッセージ462、レベル16、状態1、行1
再帰共通テーブル式「h $ cte」の再帰部分では、外部結合は許可されていません

これを回避するにはどうすればよいですか?どんな形でも助けていただければ幸いです。前もって感謝します。

回答:

回答№1は2

私は最終的にこれを次のように解決しました:

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の場合は0

データベース関数を作成して解決しました

のような関数を作る 「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