我有一个来自----的查询需求。 尝试使用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......旧记录相应地被设置并停用(通常是承包商转为全职员工的重命名)
- 用户离开一段时间后回来。 人力资源部未能向我们发送旧的用户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
没有HR ID。 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))
联接两个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,你的代码看起来非常正确……目前,在global_hr_id
为空时,lead(user_id)over(partition by 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秒后返回...时间长,但可管理。它返回93k条记录,因为我没有很好的方法来过滤掉根目录中的二级命中 - 你可以使用start with global_hr_id is null
,但不幸的是,并非总是这种情况。我需要再想一下如何过滤这些内容。
我已经尝试添加更复杂的开始子句,但我发现单独运行时小于1秒...但是一起运行需要90分钟 >.<
再次感谢您的帮助...继续努力。