---- からのクエリ要件があります。で解決しようとして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 つあります。情報を更新するときは、どちらかの間違いに注意する必要があります。
シナリオ:
- ユーザーには新しいユーザー ID が与えられます...古いレコードはそれに応じて設定され、非アクティブ化されます (通常、フルタイムになる請負業者の名前が変更されます)。
- ユーザーが離れてしばらくしてから戻ってきます。アカウントを接続できるように、HR は古いユーザー ID を送信できませんでした。
- システムがおかしくなり、古いレコードに新しいユーザー ID が設定されませんでした。
- データは他の何百もの点で悪い可能性があります
以下が同じユーザーであることを知る必要があり、名前やその他のフィールドに頼ることはできません...それらは一致するレコード間で異なります:
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 分かかります >.<
助けてくれてありがとう。