我有一个来自----的查询要求。试图用 解决它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
有两种用户数据来源(数据馈送)...在更新信息时,我必须注意其中任何一个中的错误。
场景:
- 一个用户被赋予了一个新的用户 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 之前,因此EX0T1100
没有。 EX000005
被赋予了一个新的用户 ID,“GL110456”,并且两者仅通过具有相同的全局 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 两个 CONNECT BY 查询不起作用......我没有得到调平。
这是我想看到的...我可以接受我必须区分并用作子查询的结果集。我也可以接受 ROOTUSER 列中的三个用户 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
想法?
更新
Nicholas,您的代码看起来非常像正确的轨道......目前,当为空时,lead(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
我经常想将空值视为分区中的单独记录,但我从来没有找到一种方法来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 秒后返回……很长,但易于管理。它返回 93k 记录,因为我没有从根目录中过滤级别 2 命中的好方法 - 你有start with global_hr_id is null
,但不幸的是,情况并非总是如此。我将不得不考虑更多关于如何过滤掉这些内容。
我之前尝试过添加更复杂的 start with 子句,但我发现它们单独运行 < 1 秒......一起,它们需要 90 分钟 >.<
再次感谢您的帮助...为此而步履蹒跚。