2012-10-18 32 views
6

Masz ciężkie zapytanie (wykonanie 15 minut), ale zwraca więcej wyników niż potrzebuję. Jest to zapytanie CONNECT BY i otrzymuję węzły będące potomkami w wynikach węzła głównego. Tj .:Wyłączenie wyników wyświetlanych w innej kolumnie zapytania CONNECT BY

Ted 
    Bob 
    John 
Bob 
    John 
John 

Normalnie, sposób rozwiązać ten stosuje zaczynać się stanie, zazwyczaj wymagające rodzica węzła być zerowa. Ale ze względu na naturę zapytania, nie mam wartości START z wartościami, które muszę porównać, dopóki nie uzyskałem pełnego zestawu wyników. Zasadniczo próbuję podwójnie zapytać o moje wyniki, aby powiedzieć QUERY STUFF START WITH RECORDS, KTÓRE NIE SĄ W TYM STUFF.


Oto zapytanie (zbudowany z pomocą Nicholas Krasnov, tutaj: Oracle Self-Join on multiple possible column matches - CONNECT BY?):

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; 


To daje mi wyniki o związanych użytkowników (oparte off user_id zmienia nazwę lub związane identyfikatory SAP), które wyglądają tak:

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 

Potrzebuję sposobu na odfiltruj pierwszy join (select connect_by_root(user_id)..., aby wykluczyć FG096489 i A5093665 z listy głównej.


Najlepszy START WITH mogę myśleć będzie wyglądać następująco (nie testowane jeszcze):

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) 

... ale ja skutecznie wykonując moje 15 minut zapytanie dwukrotnie.

Przyjrzałem się używaniu partycji w zapytaniu, ale tak naprawdę nie ma partycji ... Chcę spojrzeć na pełny zestaw wyników new_user_ids. Zbadałem również funkcje analityczne, takie jak ranga() ... moja torba trików jest pusta.

Wszelkie pomysły?


Wyjaśnienie

Powodem nie chcę dodatkowych zapisów na liście korzeni dlatego chcę tylko jedną grupę wyników dla każdego użytkownika. I.E., jeśli Bob Smith miał w trakcie swojej kariery cztery konta (ludzie przychodzą i odchodzą często, jako pracownicy i/lub kontrahenci), chcę pracować z zestawem kont, które wszystkie należą (ed) do Boba Smitha.

Jeśli Bob przybył tutaj jako wykonawca, zamieniony na pracownika, po lewej stronie, wrócił jako kontrahent w innym kraju, a następnie odszedł/zwrócił do prawnego organu, który jest teraz w naszym systemie SAP, jego nazwa/nazwa może zmienić nazwę konta wyglądać następująco:

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) 

w powyższym przykładzie, cztery rachunki są połączone albo new_user_id pola, który został ustawiony, gdy użytkownik został przemianowany lub za posiadające ten sam identyfikator systemu SAP.

Ponieważ HR często nie postępuje zgodnie z procesem biznesowym, powracający użytkownicy mogą skończyć z każdym z czterech przywracanych do nich identyfikatorów. Muszę przeanalizować wszystkie identyfikatory dla Boba Smitha i powiedzieć "Bob Smith może przywrócić tylko TE110001" i wykrzyczeć błąd, jeśli próbują przywrócić coś innego. Muszę to zrobić dla ponad 90 000 rekordów.

Pierwsza kolumna "Bob Smith" jest po prostu identyfikatorem grupy powiązanych rachunków. W moim oryginalnym przykładzie używam identyfikatora użytkownika root jako identyfikatora (np. US0T0001). Jeśli używam imion/nazwisk w celu identyfikacji użytkowników, kończę na kolizjach.

Więc Bob Smith będzie wyglądać następująco:

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) 

... gdzie 1, 2, 3, 4 są poziomy w heirarchy.

Ponieważ wszystkie US0T0001, US001101, EB0T0001 i TE110001 są uwzględnione, nie chcę dla nich innej grupy. Ale wyniki mam teraz mają rachunki te wymienione w wielu grupach:

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     

Powoduje to dwa problemy:

  1. Kiedy zapytanie wyniki dla identyfikatora użytkownika, otrzymuję trafień z wielu grup
  2. Każda grupa zgłasza inny oczekiwany identyfikator użytkownika dla Boba Smitha.


Pytałeś rozszerzonego zestawu rekordów ... oto niektóre rzeczywiste dane:

-- 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 

Nie wiem, czy wszystko, co czyni go bardziej zrozumiałym informacji lub uczyni Twoje oczy cofnąć do swojej głowa:)

Dzięki za obejrzenie tego!

+0

nie jest dla mnie jasne, dlaczego FG096489 i A5093665 powinny zostać wykluczone z listy root - czy to dlatego, że są one root_users z new_user_id ma wartość null, czy co? Można podać pełniejszy przykład danych wyjściowych z kwerendy, abyśmy mogli zobaczyć kilka dodatkowych kombinacji - z tylko 2 identyfikatorami użytkowników wszystko pojawia się we wszystkich kolumnach, trudno jest zobaczyć wzór. –

+0

Jedynym powodem wykluczenia ich z listy jest to, że chcę, aby były wykluczone:) Jestem otwarty na inne projekty, ale to, co próbuję zrobić z wynikami, wymaga tylko jednej grupy przypadającej na jeden powiązany zbiór użytkowników. Postaram się wyjaśnić więcej w pytaniu, dzięki! –

+0

Czy jesteś w stanie prowadzić zapytanie według daty? Innymi słowy "STARTING WITH FirstEmployment" –

Odpowiedz

1

Myślę, że mam. Pozwoliliśmy sobie na utrwalenie się w porządku chronologicznym, podczas gdy w rzeczywistości nie ma to znaczenia. Twoja klauzula START WITH powinna mieć wartość "NEW_USER_ID IS NULL".

Aby uzyskać porządek chronologiczny, można "ZAMÓW PRZEZ cudroot.node_level * -1".

Polecam również, aby spojrzeć na użycie klauzuli WITH, aby utworzyć dane podstawowe i wykonać heirarchiczne zapytanie na ten temat.

+0

Próbowałem, że ... 'new_user_id' ma wartość null, nie zawsze wskazuje węzeł główny: przykłady, które dodałem, Lars van Malen ma zerowy "nowy_użytkownik" dla wszystkich trzech identyfikatorów użytkowników ... są one połączone przez identyfikator SAP ID.Nie mogę powiedzieć, że początek gdzie identyfikator SAP jest zerowy, lub oba mają wartość zerową lub jeden ma wartość zerową, a druga jest zapełniona, ponieważ w każdym przypadku są wyjątki. Muszę znaleźć sposób na powiedzenie "żaden inny węzeł nie jest rodzicem tego węzła". –

+0

Nie udało mi się wykonać polecenia SIBLINGS dla niektórych Powód ... Zawsze mi mówiono, że nie mogę go użyć, mimo że zapytanie to POŁĄCZENIE PRZEJŚĆ, ale szukam możliwości tam. JOC, kiedy piszesz "ZAMÓW PRZEZ Cudroot.node_level * -1". .. Nigdy nie widziałem zamówienia w tym formacie lub przy użyciu gwiazdki. Co to oznacza w przypadku sortowania? –

+0

'czasy węzłów minus 1'. Czy jesteś w stanie wygenerować widok danych, które dają zapisy w formie, z którą możemy pracować - innymi słowy, w polu o nazwie Parent_ID? Jeśli tak, możesz wykonać swoje heirarchiczne zapytanie na ten temat. –

1

Być może potrzebujesz tutaj wielu zapytań. Każde zapytanie znajdzie podzbiór rekordów, które próbujesz znaleźć. Każde zapytanie będzie miejmy nadzieję prostsze i szybsze niż pojedyncze, gigantyczne zapytanie. Coś jak:

  1. gdzie użytkownika NEW_USER_ID jest nieważna i ID SAP jest null
  2. gdzie użytkownika NEW_USER_ID nie jest null i identyfikator systemu SAP jest null
  3. gdzie użytkownika NEW_USER_ID jest nieważna i ID SAP nie jest null
  4. gdzie użytkownika NEW_USER_ID jest not null i SAP ID nie jest null

(są to przykłady mankietów)

myślę część p Roblem z rozwiązaniem tej zagadki jest to, że przestrzeń problemu jest zbyt duża. Dzieląc ten problem na mniejsze części, każdy element będzie działał.