3

---- からのクエリ要件があります。で解決しようとしてCONNECT BYいますが、必要な結果が得られないようです。


表 (簡略化):

create table CSS.USER_DESC (
    USER_ID          VARCHAR2(30) not null,
    NEW_USER_ID      VARCHAR2(30),
    GLOBAL_HR_ID     CHAR(8)
)

-- USER_ID       is the primary key
-- NEW_USER_ID   is a self-referencing key
-- GLOBAL_HR_ID  is an ID field from another system

ユーザー データのソース (データ フィード) は 2 つあります。情報を更新するときは、どちらかの間違いに注意する必要があります。


シナリオ:

  1. ユーザーには新しいユーザー ID が与えられます...古いレコードはそれに応じて設定され、非アクティブ化されます (通常、フルタイムになる請負業者の名前が変更されます)。
  2. ユーザーが離れてしばらくしてから戻ってきます。アカウントを接続できるように、HR は古いユーザー ID を送信できませんでした。
  3. システムがおかしくなり、古いレコードに新しいユーザー ID が設定されませんでした。
  4. データは他の何百もの点で悪い可能性があります


以下が同じユーザーであることを知る必要があり、名前やその他のフィールドに頼ることはできません...それらは一致するレコード間で異なります:

ROOTUSER    NUMROOTS   NODELEVEL  ISLEAF    USER_ID    NEW_USER_ID  GLOBAL_HR_ID   USERTYPE      LAST_NAME         FIRST_NAME  
-----------------------------------------------------------------------------------------------------------------------------
EX0T1100    2          1          0         EX0T1100   EX000005                    CONTRACTOR    VON DER HAAVEN    VERONICA    
EX0T1100    2          2          1         EX000005                00126121       EMPLOYEE      HAAVEN, VON DER   VERONICA    
GL110456    1          1          1         GL110456                00126121       EMPLOYEE      VONDERHAAVEN      VERONICA    


EXOT1100フィールドでEX000005適切に接続されていNEW_USER_IDます。名前の変更は、グローバル HR ID が存在する前に行われたため、グローバル HR ID はありEX0T1100ません。 EX000005には新しいユーザー ID 'GL110456' が与えられ、この 2 つは同じグローバル HR ID を持つことによってのみ接続されます。

データのクリーンアップはオプションではありません。


これまでのクエリ:

select connect_by_root cud.user_id RootUser, 
       count(connect_by_root cud.user_id) over (partition by connect_by_root cud.user_id) NumRoots, 
       level NodeLevel, connect_by_isleaf IsLeaf, --connect_by_iscycle IsCycle,
       cud.user_id, cud.new_user_id, cud.global_hr_id,
       cud.user_type_code UserType, ccud.last_name, cud.first_name
from   css.user_desc cud
where  cud.user_id in ('EX000005','EX0T1100','GL110456')
-- Using this so I don't get sub-users in my list of root users...
-- It complicates the matches with GLOBAL_HR_ID, however
start with cud.user_id not in (select cudsub.new_user_id 
                               from   css.user_desc cudsub 
                               where  cudsub.new_user_id is not null)
connect by nocycle (prior new_user_id = user_id);


さまざまな句を試しましCONNECT BYたが、どれもまったく正しくありません。

-- As a multiple CONNECT BY
connect by nocycle (prior global_hr_id = global_hr_id)
connect by nocycle (prior new_user_id  = user_id)

-- As a compound CONNECT BY
connect by nocycle ((prior new_user_id = user_id)
                     or (prior global_hr_id = global_hr_id 
                         and user_id != prior user_Id))


UNIONing 2 つの CONNECT BY クエリが機能しません... レベリングができません。

これが私が見たいものです...区別してサブクエリとして使用する必要がある結果セットで問題ありません。また、ROOTUSER 列の 3 つのユーザー ID のいずれでも問題ありません...それらが同じユーザーであることを知る必要があるだけです。

ROOTUSER    NUMROOTS   NODELEVEL  ISLEAF    USER_ID    NEW_USER_ID  GLOBAL_HR_ID   USERTYPE      LAST_NAME         FIRST_NAME  
-----------------------------------------------------------------------------------------------------------------------------
EX0T1100    3          1          0         EX0T1100   EX000005                    CONTRACTOR    VON DER HAAVEN    VERONICA    
EX0T1100    3          2          1         EX000005                00126121       EMPLOYEE      HAAVEN, VON DER   VERONICA    
EX0T1100    3         (2 or 3)    1         GL110456                00126121       EMPLOYEE      VONDERHAAVEN      VERONICA    


アイデア?


アップデート

ニコラス、あなたのコードは正しいトラックに非常によく似ています... 現時点では、が nulllead(user_id) over (partition by global_hr_id)の場合に誤ったヒットが発生します。global_hr_id例えば:

USER_ID   NEW_USER_ID   CHAINNEWUSER   GLOBAL_HR_ID   LAST_NAME   FIRST_NAME
FP004468                FP004469                      AARON       TIMOTHY
FP004469                                              FOONG       KOK WAH

null をパーティション内の個別のレコードとして扱いたいと思ったことはよくありますが、うまくいく方法が見つかりませんでしたignore nulls。これは私が望んでいたことをしました:

decode(global_hr_id,null,null,lead(cud.user_id ignore nulls) over (partition by global_hr_id order by user_id)

...しかし、もっと良い方法があるはずです。本格的なユーザー データ (約 40,000 ユーザー) では、まだクエリを完了できていません。global_hr_idとの両方new_user_idが索引付けされています。


アップデート

クエリは約 750 秒後に返されます...長いですが、扱いやすいです。ルートからレベル 2 のヒットをフィルタリングする良い方法がないため、93k レコードが返されますstart with global_hr_id is null。それらをどのように除外するかについて、もう少し考えなければなりません。

以前より複雑な start with 句を追加しようとしましたが、別々に実行すると < 1 秒... 一緒にすると 90 分かかります >.<

助けてくれてありがとう。

4

1 に答える 1

3

1 人のユーザーのみのデータのサンプルを提供しました。もう少しあった方がいいです。とにかく、このようなものを見てみましょう。

SQL> with user_desc(USER_ID, NEW_USER_ID,  GLOBAL_HR_ID)as(
  2    select 'EX0T1100',  'EX000005',  null          from dual union all
  3    select 'EX000005',   null,       00126121      from dual union all
  4    select 'GL110456',   null,       00126121      from dual
  5  )
  6  select connect_by_root(user_id) rootuser
  7       , count(connect_by_root(user_id)) over(partition by connect_by_root(user_id)) numroot
  8       , level nodlevel
  9       , connect_by_isleaf
 10       , user_id
 11       , new_user_id
 12       , global_hr_id
 13    from (select user_id
 14               , coalesce(new_user_id, usr) new_user_id1
 15               , new_user_id
 16               , global_hr_id
 17            from ( select user_id
 18                        , new_user_id
 19                        , global_hr_id
 20                        , decode(global_hr_id,null,null,lead(user_id) over (partition by global_hr_id order by user_id)) usr
 21                    from user_desc
 22                 )
 23         )
 24  start with global_hr_id is null
 25  connect by prior new_user_id1 = user_id
 26  ;

結果:

ROOTUSER    NUMROOT   NODLEVEL CONNECT_BY_ISLEAF USER_ID  NEW_USER_ID GLOBAL_HR_ID
-------- ---------- ---------- ----------------- -------- ----------- ------------
EX0T1100          3          1                 0 EX0T1100 EX000005    
EX0T1100          3          2                 0 EX000005                   126121
EX0T1100          3          3                 1 GL110456                   126121
于 2012-10-15T02:38:06.270 に答える