지난 번에 배운 계층 쿼리를 활용해서, 이번에는 사용자별 Role 에 따른 접근 목록을 가져오는 쿼리를 작성 중입니다.
일주일 넘게 삽질하고 있지만, 원하는 결과를 못만들고 있어, 질문 올려봅니다.
원하는 결과는, 사용자마다 한개 이상의 Role 이 지정될 수 있기 때문에,
계층 접근 목록을 Role 마다 나눠서 보여주려고 합니다.
현재 제 쿼리는 계층 중간 중간에 섞여서 나오고 있습니다.
WITH usr(usr_id, usr_kr, usr_sts) AS ( SELECT 115, 'John', 1 FROM dual UNION ALL SELECT 150, 'Kole', 1 FROM dual UNION ALL SELECT 200, 'Tony', 0 FROM dual ), test_elm(test_elm_id, test_parent_elm_id) AS ( SELECT 1, NULL FROM dual UNION ALL SELECT 100, 1 FROM dual UNION ALL SELECT 101, 1 FROM dual UNION ALL SELECT 102, 1 FROM dual UNION ALL SELECT 2, NULL FROM dual UNION ALL SELECT 200, 2 FROM dual UNION ALL SELECT 201, 2 FROM dual UNION ALL SELECT 202, 2 FROM dual ), usr_rl(usr_id, rl_id) AS ( SELECT 115, 8 FROM dual UNION ALL SELECT 115, 9 FROM dual UNION ALL SELECT 150, 9 FROM dual UNION ALL SELECT 200, 7 FROM dual ), test_elm_rl(test_elm_id, rl_id, sel_checked, ins_checked, updt_checked, dlt_checked) AS ( SELECT 1, 8, 1, 1, 1, 1 FROM dual UNION ALL --parent SELECT 2, 8, 1, 1, 1, 1 FROM dual UNION ALL --parent SELECT 102, 8, 0, 0, 0, 0 FROM dual UNION ALL --child SELECT 200, 8, 0, 0, 0, 0 FROM dual UNION ALL --child SELECT 1, 9, 1, 1, 1, 1 FROM dual --parent ) SELECT * FROM (SELECT a.usr_id, a.usr_kr, b.test_parent_elm_id, b.test_elm_id , c.rl_id , SIGN(d.sel_checked + d.ins_checked + d.updt_checked + d.dlt_checked) AS checked , 'Role' AS Per_Grp FROM usr a CROSS JOIN test_elm b -- returns 24 rows (= 3 users x 8 elements ) LEFT OUTER JOIN usr_rl c ON a.usr_id = c.usr_id -- returns 32 rows (= 16 elements from one user and 16 elements from two users ) LEFT OUTER JOIN test_elm_rl d ON c.rl_id = d.rl_id AND b.test_elm_id = d.test_elm_id WHERE a.usr_sts = 1 ORDER BY a.usr_id, b.test_elm_id ) START WITH test_parent_elm_id IS NULL AND checked = 1 CONNECT BY prior usr_id = usr_id AND prior test_elm_id = test_parent_elm_id AND NVL(checked, 1) != 0 ORDER SIBLINGS BY usr_id, test_elm_id
CONNECT BY prior usr_id = usr_id AND prior test_elm_id = test_parent_elm_id AND NVL(checked, 1) != 0
이 부분에서 특히 prior usr_id = usr_id 를 이해를 못했는데..
역시나 이해 못한 부분이 문제이네요.
prior rl_id = rl_id 를 추가해 보니 원하는 모습대로 결과 나왔지만,...........
prior usr_id = usr_id 와 prior rl_id = rl_id
어떤 역할과 의미인지 설명해 주시면 감사하겠습니다.
이해가 잘 안되네요. 같은 값을 비교하라??
CONNECT BY prior usr_id = usr_id AND prior test_elm_id = test_parent_elm_id AND prior rl_id = rl_id AND NVL(checked, 1) != 0
prior은 앞의 ,이전의 와 같은뜻을 가지고 있습니다.
START WITH test_parent_elm_id IS NULL AND checked = 1 /* test_parent_elm_id 가 null 이고 checked =1 인 조건의 row가 [시작row] */ CONNECT BY prior usr_id = usr_id AND prior test_elm_id = test_parent_elm_id AND NVL(checked, 1) != 0
처리순서를 보죠.
1.start with 구문에서 "시작row" 를 찾아냅니다. 1개 일 수도 있고 여러개 일 수도 있습니다.
2.그 다음 CONNECT BY prior usr_id = usr_id 조건을 찾습니다.
prior usr_id 는 "시작row"의 usr_id 컬럼입니다. 이 값과 같은 usr_id 를 가진 row를 찾습니다.
찾았습니까? 찾았으면 해당 row는 자식 node로 기억됩니다. 다음으로 갑니다.
3. 이번엔 prior usr_id 가 2 에서 찾은 row의 usr_id 컬럼값입니다.
이 값을 기준으로 역시 조건에 맞는 usr_id 를 가진 컬럼을 찾습니다.
역시 이번 usr_id는 자식Node로 기억됩니다.
이런식으로 현재 row의 이전 row를 끊임없이 찾아내는 문장입니다.
좀더 설명이 잘되어있거나 예시를 동반한 책등을 찾아보시길 권장합니다.