Je travaille sur un projet de migration et je dois convertir la requête Oracle suivante en son équivalent 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
J'utilise des CTE pour ce faire. Jusqu'à présent, j'ai trouvé ce qui suit:
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
La requête traduite donnant les erreurs suivantes:
Msg 467, niveau 16, état 1, ligne 1
Les fonctions GROUP BY, HAVING ou d'agrégation ne sont pas autorisées dans la partie récursive d'une expression de table commune récursive "h $ cte".Msg 462, niveau 16, état 1, ligne 1
La jointure externe n'est pas autorisée dans la partie récursive d'une expression de table commune récursive "h $ cte"
Comment contourner cela? Toute aide sous quelque forme que ce soit est grandement appréciée. Merci d'avance.
Réponses:
2 pour la réponse № 1"J'ai finalement résolu ce problème en:
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
Comme je n'étais pas autorisé à écrire des jointures externes et des fonctions GROUP BY, HAVING ou d'agrégation à l'intérieur d'un membre récursif de CTE, je l'ai déplacé à l'extérieur sous un nouveau CTE. Cela fonctionnait comme un charme.
À votre santé !!!
0 pour la réponse № 2
Je l'ai résolu en créant une fonction de base de données
Créer une fonction comme "ufn_GetParentPath" l'utiliser au lieu de "SYS_CONNECT_BY_PATH" Qui passe ID
en paramètre.
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