从多个表返回最大日期加入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 bywhere 之后。所以你需要一个子查询,select * from (...old query...) as SubQueryAlias where rownum = 1。通常比 dense_rank() 之类的分析函数执行得更好。

以上是关于从多个表返回最大日期加入oracle的主要内容,如果未能解决你的问题,请参考以下文章

加入仅包括表中的最大日期 [重复]

Oracle 选择多条记录的最大日期

返回从最新日期算起的最后 365 内的值 ORACLE SQL

使用 Athena / Presto 从多个表返回 SQL 数据,受 1 个表中的日期范围限制

如何加入表格并按最大日期选择 [重复]

ORACLE SQL:仅返回后来加入或从主要渠道不同的非主要帐户持有人?