从多个表返回最大日期加入oracle
Posted
技术标签:
【中文标题】从多个表返回最大日期加入oracle【英文标题】:Return max date from multiple tables join oracle 【发布时间】:2011-09-03 17:47:24 【问题描述】:我有 4 个表,其中包含我要检索的以下相关信息。
表:Staff_profile(STAFF_ID、STAFF_USERNAME、STAFF_NAME、STAFF_JOB_ID、STAFF_FACULTY_ID、STAFF_OFF_TEL、STAFF_EMAIL) - 保存员工信息
表:RFMUSERHISTORY (uh_staff_id, UH_DATETIME) - 保存登录历史记录
表:RFMUSERROLEJOBMAP (role_id, job_id) - 映射 role-2-job [这是因为作业表已经存在,并且这个新应用只选择某些作业 ID 来使用自己的角色表
表:RFMUSERROLE (USERROLE_CODE, USERROLE_ID) - 保存用户角色信息
现在我想获取上次登录(用户历史记录中该用户的最大日期)详细信息,包括任何登录的特定人员的角色和员工详细信息。我的代码遇到了问题,最后只好选择了所有记录对于具有 UH_datetime 有序 desc 的用户,我可以选择最新的最高记录。
这是我当前的代码(如上所述非常低效):
SELECT a.STAFF_ID, a.STAFF_USERNAME, a.STAFF_NAME, a.STAFF_JOB_ID, a.STAFF_FACULTY_ID,
a.STAFF_OFF_TEL, a.STAFF_EMAIL, to_CHAR(b.UH_DATETIME,'Dy DD-MM-YYYY HH24:MI:SS')
AS UH_DATETIME, e.USERROLE_CODE, e.USERROLE_ID
FROM STAFF_PROFILE a
LEFT JOIN RFMUSERHISTORY b ON STAFF_ID=b.uh_staff_id
LEFT JOIN RFMUSERROLEJOBMAP d ON a.STAFF_JOB_ID=d.job_id
LEFT JOIN RFMUSERROLE e ON d.role_id=e.userrole_id
WHERE STAFF_ID=:eid1 ORDER BY b.UH_DATETIME DESC
【问题讨论】:
【参考方案1】:您可以使用分析函数对行进行排名,然后选择最近的行。如果您真的只是为单个STAFF_ID
选择数据,这可能不会比将原始查询嵌套在使用ROWNUM
谓词选择行的外部查询中更有效。但是,如果您要为多名员工选择数据,这应该会更有效率。
SELECT *
FROM (
SELECT a.STAFF_ID,
a.STAFF_USERNAME,
a.STAFF_NAME,
a.STAFF_JOB_ID,
a.STAFF_FACULTY_ID,
a.STAFF_OFF_TEL,
a.STAFF_EMAIL,
to_CHAR(b.UH_DATETIME,'Dy DD-MM-YYYY HH24:MI:SS') AS UH_DATETIME,
e.USERROLE_CODE,
e.USERROLE_ID,
dense_rank() over (partition by a.staff_id order by b.uh_datetime desc) rnk
FROM STAFF_PROFILE a
LEFT JOIN RFMUSERHISTORY b ON STAFF_ID=b.uh_staff_id
LEFT JOIN RFMUSERROLEJOBMAP d ON a.STAFF_JOB_ID=d.job_id
LEFT JOIN RFMUSERROLE e ON d.role_id=e.userrole_id
WHERE STAFF_ID=:eid1
)
WHERE rnk = 1
【讨论】:
感谢您的帮助。正如您所提到的,可以为单个员工或所有员工的结果工作。新的教训,非常感谢。【参考方案2】:在您请求行之前,Oracle 不会通过网络发送行。如果您的客户端代码只请求第一行,那么您的查询应该足够高效。
另一种选择是使用rownum
将 Oracle 限制为一行:
where rownum = 1
【讨论】:
抱歉,但我注意到放置 rownum 限制器的位置可能有问题,并且返回的行不是最新日期:SELECT a.STAFF_ID, a.STAFF_USERNAME, a.STAFF_NAME, a. STAFF_JOB_ID, a.STAFF_FACULTY_ID, a.STAFF_OFF_TEL, a.STAFF_EMAIL, to_CHAR(b.UH_DATETIME,'Dy DD-MM-YYYY HH24:MI:SS') AS UH_DATETIME, e.USERROLE_CODE, e.USERROLE_ID FROM STAFF_PROFILE a LEFT JOIN RFMUSERHISTORY b ON STAFF_ID=b.uh_staff_id LEFT JOIN RFMUSERROLEJOBMAP d ON a.STAFF_JOB_ID=d.job_id LEFT JOIN RFMUSERROLE e ON d.role_id=e.userrole_id WHERE STAFF_ID='1001100821' AND rownum=1 ORDER BY b.UH_DATETIME DESC @luhfluh:order by
在where
之后。所以你需要一个子查询,select * from (...old query...) as SubQueryAlias where rownum = 1
。通常比 dense_rank()
之类的分析函数执行得更好。以上是关于从多个表返回最大日期加入oracle的主要内容,如果未能解决你的问题,请参考以下文章
返回从最新日期算起的最后 365 内的值 ORACLE SQL