by kento [SQLServer] 계층형 CTE IN 함수 리턴값 다중 ROW [2019.01.02 17:23:00]
안녕하세요
ORACLE 개발하다가 MS SQL 로 쿼리 짤라니까
안되는 점이 너무 많네요
도움좀 받고 싶어서 글을 남기게 되었습니다.
혼자 찾아 보는것도 지치네요 ....
오라클 같으면 제약 없이 계층형(CTE) 조건문에 쓰는데
MS SQL은 WITH 위에 조건이 있으면 안되는거같더라구요
2가지 방법으로 접근해 봤는데
다른방법 있으면 지도좀 부탁드립니다.
-- 방법 1 SELECT H.ID , E.ID FROM USER H, ERP E WHERE H.USE_YN=1 AND E.CNT > 0 UNION ALL SELECT H.ID , E.ID FROM USER H, ERP E WHERE E.ID IN ( -- 이부분이 안됩니다 ㅠ.ㅠ MS SQL 에서는 WITH 문 위에 다른것들을 못넣더라구요... -- 이 위에 또 UNION ALL 절이 있어서 WITH 문을 앞으로 뺄수가 없어요 ... WITH TREE AS ( SELECT ID FROM ERP WHERE ID = H.ID -- (상위에 값을 START WITH) UNION ALL SELECT ID FROM ERP AS CHILD , TREE PARENT WHERE CHILID.PARENTID = PARENT.ID ) SELECT ID FROM TREE ) -- 방법2 SELECT H.ID , E.ID FROM USER H, ERP E WHERE H.USE_YN=1 AND E.CNT > 0 UNION ALL SELECT H.ID , E.ID FROM USER H, ERP E WHERE E.ID IN ( -- 함수를 만들어서 호출하는 방법. 함수는 CTE문 -- 하지만 리턴값이 다중 ROW인데 첫번째 값만 리턴네요 ;; 함수는 바로 밑에 써볼께요 dbo.treeCte(H.id) ) -- 함수문 CREATE FUNCTION treeCte (@ID NUMERIC) RETURNS NUMERIC(8) -- 다중 ROW 값으로 리턴 받으려면 어떻게 선언해야되는지 모르겠네요 .. NUMERIC 으로 선언하니 첫번째 값만 리턴합니다.. AS BEGIN DECLARE @V_RETURN NUMERIC(8) WITH TREE AS ( SELECT ID FROM ERP WHERE ID = @ID UNION ALL SELECT ID FROM ERP AS CHILD , TREE PARENT WHERE CHILID.PARENTID = PARENT.ID ) SELECT @V_RETURN=ID FROM TREE RETURN @V_RETURN; END
쿼리 중간에서 특정 ID 를 시작조건으로 계층 전개 하지 마시고
쿼리 시작할 때 모든 ID 를 시작조건으로 계층 전개 하세요.
그 후에 조인을 하든 IN 조건으로 쓰던 하면 될 듯 하네요.
그리고, union 위쪽 쿼리에 user 와 erp 사이에 조인 조건이 없는거 맞나요? 이상하네요?
WITH tree AS ( SELECT id root_id , id FROM erp UNION ALL SELECT p.root_id , c.id FROM tree p INNER JOIN erp c ON p.id = c.parentid ) SELECT h.id , t.id FROM user h INNER JOIN tree t ON h.id = t.root_id ;
답변 감사합니다 ^^
진심으로 머리 숙여 감사드립니다 ^^
한수 배워갑니다 절대 안까먹을거같네요 ㅋㅋ
MS-SQL 에서 계층형 쿼리에서
타 테이블과 조인하거나 UNION 쓰려면
WITH 가 맨 위에 선언되어야 햇네요 .. (아직도 적응이 안되네요 ;; )
저와 같이 삽질하지말라고 얕은 지식이지만 그래도 공유 합니다 ;;
WITH tree AS ( SELECT id root_id , id FROM erp UNION ALL SELECT p.root_id , c.id FROM tree p INNER JOIN erp c ON p.id = c.parentid ) SELECT t.rootid , t.id from tree t -- 요롷게요 ㅋㅋ 이 밑에서 오라클과 같이 타 테이블과 조인해서 쓸수 있더라구요 WHERE t.id in (SELECT ID FROM XXXX ) UNION ALL -- 이 밑으로 UNION 도 쓸수 있구요 SELECT ROOTID, ID FROM XXXX ; -- 2개의 계층형 쿼리를 맨위에 선언해서 밑에서 조인 할수도 있어요 ~ WITH tree1 AS ( SELECT id root_id , id FROM erp UNION ALL SELECT p.root_id , c.id FROM tree p INNER JOIN erp c ON p.id = c.parentid ) , tree2 AS -- 여기에 다른 계층형 쿼리를 한번 더 선언해서 밑에서 조인걸면 될거같아요 ( SELECT id root_id , id FROM erp UNION ALL SELECT p.root_id , c.id FROM tree p INNER JOIN erp c ON p.id = c.parentid ) SELECT t.rootid , t.id from tree1 t WHERE t.id in (SELECT ID FROM XXXX ) UNION ALL SELECT t2.rootid, t2.id FROM xxx h INNER JOIN tree2 t2 ON h.id = t2.id;