2012-10-18 3 views
6

쿼리가 많이 걸리지 만 (실행하는 데 15 분 소요), 필 요한 것보다 많은 결과가 반환됩니다. 그것은 CONNECT BY 쿼리이고, 루트 노드 결과에서 자손 인 노드를 얻고 있습니다. 즉 :CONNECT BY 쿼리의 다른 열에 나타나는 결과 제외

Ted 
    Bob 
    John 
Bob 
    John 
John 

일반적으로이 문제를 해결하는 방법은 널 (null)로 일반적으로 노드의 부모를 필요 조건을 가진 START를 사용하고 있습니다. 그러나 쿼리의 특성상 전체 결과 집합을 얻을 때까지 필자가 비교해야하는 START WITH 값이 없습니다. 저는 기본적으로 쿼리 결과를 두 번 쿼리하여 QUERY STUFF START와 그 기록에없는 기록을 말하려고합니다. 여기


가 (: Oracle Self-Join on multiple possible column matches - CONNECT BY? 여기 Nicholas Krasnov의 도움으로 내장) : 쿼리의이 날에 대한 관련 사용자에게 결과를 제공

select cudroot.root_user, cudroot.node_level, cudroot.user_id, cudroot.new_user_id, 
     cudbase.* -- Not really, just simplyfing 
from css.user_desc cudbase 
    join (select connect_by_root(user_id) root_user, 
       user_id     user_id,   
       new_user_id    new_user_id, 
       level     node_level 
     from (select cudordered.user_id,  
         coalesce(cudordered.new_user_id, cudordered.nextUser) new_user_id 
       from (select cud.user_id, 
           cud.new_user_id, 
           decode(cud.global_hr_id, null, null, lead(cud.user_id ignore nulls) over (partition by cud.global_hr_id order by cud.user_id)) nextUser 
         from css.user_desc cud 
          left join gsu.stg_userdata gstgu 
          on (gstgu.user_id = cud.user_id 
           or (gstgu.sap_asoc_global_id = cud.global_hr_id)) 
         where upper(cud.user_type_code) in ('EMPLOYEE','CONTRACTOR','DIV_EMPLOYEE','DIV_CONTRACTOR','DIV_MYTEAPPROVED')) cudordered) 
     connect by nocycle user_id = prior new_user_id) cudroot 
    on cudbase.user_id = cudroot.user_id 
order by 
     cudroot.root_user, cudroot.node_level, cudroot.user_id; 


(USER_ID 떨어져 이름을 변경 기반 또는 SAP ID를 관련)이 모양은 다음과 같습니다.

ROOT_ID  LEVEL USER_ID   NEW_USER_ID 
------------------------------------------------ 
A5093522 1  A5093522  FG096489 
A5093522 2  FG096489  A5093665 
A5093522 3  A5093665   
FG096489 1  FG096489  A5093665 
FG096489 2  A5093665 
A5093665 1  A5093665 

내가 필요한 것은 첫 번째 join (select connect_by_root(user_id)...을 필터링하여 루트 목록에서 FG096489A5093665을 제외하십시오.


내가 (안 테스트 아직)과 같을 것이라고 생각할 수있는 최선의 START WITH

:

start with user_id not in (select new_user_id 
          from (select coalesce(cudordered.new_user_id, cudordered.nextUser) new_user_id 
            from (select cud.new_user_id, 
                decode(cud.global_hr_id, null, null, lead(cud.user_id ignore nulls) over (partition by cud.global_hr_id order by cud.user_id)) nextUser 
              from css.user_desc cud 
              where upper(cud.user_type_code) in ('EMPLOYEE','CONTRACTOR','DIV_EMPLOYEE','DIV_CONTRACTOR','DIV_MYTEAPPROVED')) cudordered) 
          connect by nocycle user_id = prior new_user_id) 

...하지만 효과적으로 두 번 내로 15 분 쿼리를 실행하고 있습니다.

쿼리에서 파티션을 사용하여 보았습니다.하지만 실제로 파티션이 없습니다 ... new_user_ids의 전체 결과 집합을보고 싶습니다. rank()와 같은 분석 함수도 살펴 보았습니다. 트릭을 담은 가방은 비어 있습니다.

아이디어가 있으십니까? 난 단지 각 사용자에 대한 결과를 하나 개의 그룹을 원하기 때문에


대한 설명

내가 루트 목록에 추가 기록을하지 않으려는 이유입니다. I.E. 밥 스미스가 여기에 자신의 경력 중에 4 명의 계좌를 가지고 있다면 (사람들은 자주 와서 직원 및/또는 계약자로 출근 함), Bob Smith에게 속한 모든 계좌로 작업하고 싶습니다.

Bob이 계약자로 왔을 때 왼쪽 직원이 다른 나라의 계약자로 다시 돌아 왔고 현재 SAP 시스템에있는 법적 조직으로 돌아갔습니다. 그의 계좌 이름 변경/체인은 처럼 : 위 예에서

Bob Smith CONTRACTOR ---- US0T0001 -> US001101 (given a new ID as an employee) 
Bob Smith EMPLOYEE  ---- US001101 -> EB0T0001 (contractor ID for the UK) 
Bob Smith CONTRACTOR SAP001 EB0T000T    (no rename performed) 
Bob Smith EMPLOYEE SAP001 TE110001    (currently-active ID) 

, 네 계정 사용자가 바뀌거나 동일한 SAP의 ID를 갖는 통해 때 설정 한 new_user_id 필드 중 하나에 의해 연결되어있다.

HR은 비즈니스 프로세스를 자주 따르지 않으므로 반환하는 사용자는 4 개의 ID 중 하나라도 복원 될 수 있습니다. Bob Smith의 모든 ID를 분석하고 "Bob Smith는 TE110001 만 복원 할 수 있습니다"라고 말하면서 다른 것을 복원하려고 시도하면 오류가 다시 발생합니다. 90,000 개 이상의 레코드를 처리해야합니다.

첫 번째 열 "Bob Smith"는 연결된 계정 그룹의 식별자입니다. 원래 예제에서는 루트 사용자 ID를 식별자 (예 : US0T0001)로 사용하고 있습니다. 성/이름을 사용하여 사용자를 식별하면 충돌이 발생합니다.

그래서 밥 스미스는 다음과 같이 보일 것이다 : 1, 2, 3, 4는 계층 구조의 수준이다

US0T0001 1 CONTRACTOR ---- US0T0001 -> US001101 (given a new ID as an employee) 
US0T0001 2 EMPLOYEE  ---- US001101 -> EB0T0001 (contractor ID for the UK) 
US0T0001 3 CONTRACTOR SAP001 EB0T0001    (no rename performed) 
US0T0001 4 EMPLOYEE SAP001 TE110001    (currently-active ID) 

....

US0T0001, US001101, EB0T0001 및 TE110001이 모두 고려되었으므로 다른 그룹은 필요하지 않습니다. 하지만 지금은 그 계정이 여러 그룹에 열거 한 한 결과는 : 나는 사용자 ID에 대한 결과를 조회 할 때

  1. , 나는 여러 그룹
  2. 을에서 안타를 얻을 :

    US001101 1 EMPLOYEE  ---- US001101 -> EB0T0001 (
    US001101 2 CONTRACTOR SAP001 EB0T0001     
    US001101 3 EMPLOYEE SAP001 TE110001    
    
    EB0T0001 1 CONTRACTOR SAP001 EB0T0001    
    EB0T0001 2 EMPLOYEE SAP001 TE110001     
    
    US001101 1 EMPLOYEE SAP001 TE110001     
    

    이 두 가지 문제가 발생

  3. 각 그룹은 Bob Smith에 대해 예상되는 다른 사용자 ID를보고합니다.


당신은 기록의 확장 된 세트를 요청 ... 여기에 몇 가지 실제 데이터입니다 : 모든 정보가 명확하게하거나 눈으로 롤백 할 것입니다 경우

-- NumRootUsers tells me how many accounts are associated with a user. 
-- The new user ID field is explicitly set in the database, but may be null. 
-- The calculated new user ID analyzes records to determine what the next related record is 

      NumRoot     New User Calculated 
RootUser Users Level UserId ID Field New User ID SapId  LastName  FirstName 
----------------------------------------------------------------------------------------------- 
BG100502 3  1  BG100502 BG1T0873 BG1T0873     GRIENS VAN  KION 
BG100502 3  2  BG1T0873 BG103443 BG103443     GRIENS VAN  KION 
BG100502 3  3  BG103443       41008318 VAN GRIENS  KION 

-- This group causes bad matches for Kion van Griens... the IDs are already accounted for, 
-- and this group doesn't even grab all of the accounts for Kion. It's also using a new 
-- ID to identify the group 
BG1T0873 2  1  BG1T0873 BG103443 BG103443     GRIENS VAN  KION 
BG1T0873 2  2  BG103443       41008318 VAN GRIENS  KION 

-- Same here... 
BG103443 1  1  BG103443       41008318 VAN GRIENS  KION 

-- Good group of records 
BG100506 3  1  BG100506    BG100778  41008640 MALEN VAN  LARS 
BG100506 3  2  BG100778    BG1T0877  41008640 MALEN VAN  LARS 
BG100506 3  3  BG1T0877       41008640 VAN MALEN  LARS 

-- Bad, unwanted group of records 
BG100778 2  1  BG100778    BG1T0877  41008640 MALEN VAN  LARS 
BG100778 2  2  BG1T0877       41008640 VAN MALEN  LARS 

-- Third group for Lars 
BG1T0877 1  1  BG1T0877       41008640 VAN MALEN  LARS 


-- Jan... fields are set differently than the above examples, but the chain is calculated correctly 
BG100525 3  1  BG100525    BG1T0894  41008651 ZANWIJK VAN  JAN 
BG100525 3  2  BG1T0894 TE035165 TE035165  41008651 VAN ZANWIJK  JAN 
BG100525 3  3  TE035165       41008651 VAN ZANWIJK  JAN 

-- Bad 
BG1T0894 2  1  BG1T0894 TE035165 TE035165  41008651 VAN ZANWIJK  JAN 
BG1T0894 2  2  TE035165       41008651 VAN ZANWIJK  JAN 

-- Bad bad 
TE035165 1  1  TE035165       41008651 VAN ZANWIJK  JAN 


-- Somebody goofed and gave Ziano a second SAP ID... but we still matched correctly 
BG100527 3  1  BG100527    BG1T0896  41008652 STEFANI DE  ZIANO 
BG100527 3  2  BG1T0896 TE033030 TE033030  41008652 STEFANI DE  ZIANO 
BG100527 3  3  TE033030       42006172 DE STEFANI  ZIANO 

-- And we still got extra, unwanted groups 
BG1T0896 3  2  BG1T0896 TE033030 TE033030  41008652 STEFANI DE  ZIANO 
BG1T0896 3  3  TE033030       42006172 DE STEFANI  ZIANO 

TE033030 3  3  TE033030       42006172 DE STEFANI  ZIANO 


-- Mark's a perfect example of the missing/frustrating data I'm dealing with... but we still matched correctly 
BG102188 3  1  BG102188    BG1T0543  41008250 BULINS   MARK 
BG102188 3  2  BG1T0543    TE908583  41008250 BULINS   R.J.M.A. 
BG102188 3  3  TE908583       41008250 BULINS   RICHARD JOHANNES MARTINUS ALPHISIUS 

-- Not wanted 
BG1T0543 3  2  BG1T0543    TE908583  41008250 BULINS   R.J.M.A. 
BG1T0543 3  3  TE908583       41008250 BULINS   RICHARD JOHANNES MARTINUS ALPHISIUS 

TE908583 3  3  TE908583       41008250 BULINS   RICHARD JOHANNES MARTINUS ALPHISIUS 


-- One more for good measure 
BG1T0146 3  1  BG1T0146 BG105905 BG105905     LUIJENT   VALERIE 
BG1T0146 3  2  BG105905    TE034165  42006121 LUIJENT   VALERIE 
BG1T0146 3  3  TE034165       42006121 LUIJENT   VALERIE 

BG105905 3  2  BG105905    TE034165  42006121 LUIJENT   VALERIE 
BG105905 3  3  TE034165       42006121 LUIJENT   VALERIE 

TE034165 3  3  TE034165       42006121 LUIJENT   VALERIE 

확실하지 당신의 head :)

고마워!

+0

FG096489와 A5093665가 루트 목록에서 제외되어야하는 이유는 new_user_id가 null 인 root_users이거나 null이 무엇인지, 또는 우리가 볼 수 있도록 쿼리의 출력에 대한 전체 예제를 제공 할 수 있습니까? 몇 가지 조합 - 모든 열에 모두 2 개의 사용자 ID 만 나타나면 패턴을보기가 어렵습니다. –

+0

목록에서 제외시키는 유일한 이유는 내가 제외 시키길 바란다는 것입니다.) 다른 디자인에 대해 열어 보았습니다. 그러나 결과를 가지고 무엇을 하려는지 관련 사용자 집합당 하나의 그룹 만 있으면됩니다. 감사의 말로 더 많은 것을 설명하려고 노력할 것입니다! –

+0

날짜별로 쿼리를 실행할 수 있습니까? 다른 말로하면 'FirstEmployment로 시작' –

답변

1

나는 그것을 가지고 있다고 생각합니다. 우리는 연대순으로 고정 될 수있게 허용했지만 실제로는 문제가되지 않습니다. START WITH 절은 'NEW_USER_ID IS NULL'이어야합니다.

시간순으로 주문하려면 'ORDER BY cudroot.node_level * -1'을 (를) 사용할 수 있습니다.

또한 WITH 절을 사용하여 기본 데이터를 구성하고 그에 대한 계층 적 쿼리를 수행하는 것이 좋습니다.

+0

'new_user_id'가 null 인 경우 루트 노드가 항상 표시되는 것은 아닙니다. (In 내가 추가 한 예제 Lars van Malen은 세 개의 모든 사용자 ID에 대해 null new_user_id를 가지고 있습니다 ... 대신 SAP ID로 연결되어 있습니다. SAP ID가 null이거나 둘 중 하나가 null이거나 start라고 말할 수는 없습니다. 모든 경우에 예외가 있기 때문에 null이 채워지고 다른 노드는 채워집니다. "다른 노드는이 노드의 부모가 아닙니다."라는 말을 찾아야합니다. –

+0

ORDER BY SIBLINGS가 일부 노드에서 작동하도록 만들지 못했습니다. 이유는 ... 나는 항상 쿼리가 CONNECT BY인데도 사용할 수 없다는 말을 듣고있다.하지만 JOC는 "ORDER BY cudroot.node_level * -1"을 쓸 때 그 가능성을 찾고있다. .. 그 형식으로 또는 별표를 사용하여 주문을 본 적이 한번도 없었습니다. 정렬 순서는 무엇입니까? –

+0

'노드 레벨 시간에서 1을 뺀 값입니다.' 우리가 작업 할 수있는 양식으로 레코드를 생성하는 데이터 뷰를 생성 할 수 있습니까? 즉, Parent_ID라는 필드가 있습니까? 그렇다면 그에 대한 계층 적 쿼리를 수행 할 수 있습니다. –

1

아마도 여기에 여러 검색어가 필요합니다. 각 쿼리는 찾으려고하는 레코드의 하위 집합을 찾습니다. 각 쿼리는 단일 쿼리보다 훨씬 간단하고 빠릅니다. 뭔가 같은 :

  1. NEW_USER_ID가 null SAP ID는 널 (null)입니다
  2. NEW_USER_ID는 null가 아니고, SAP ID는 널 (null)입니다
  3. NEW_USER_ID가 null SAP ID는 null가 아닌 경우
  4. NEW_USER_ID입니다 NOT NULL 및 SAP ID는

    내가 페이지의 일부 생각 (이러한 커프 예제이다)

null가 아닌 이 수수께끼를 푸는 문제는 문제 공간이 너무 크다는 것입니다. 이 문제를 작은 조각으로 세분함으로써 각 조각을 실행할 수 있습니다.

관련 문제