1

我在 Oracle 数据库中有几个与员工记录相关的表。这些表中的每一个都包含三个相似的列EMPLOYEE_IDLAST_UPDATED_DTLAST_UPDATED_BY

我的目标是为最新更新投影EMPLOYEE_ID,LAST_UPDATED_DT和列。LAST_UPDATED_BY

以下是这些列的 DDL:

create table EMPLOYEE
(
  EMPLOYEE_ID INT,
  NAME VARCHAR(100),
  LAST_UPDATED_BY VARCHAR(200),
  LAST_UPDATED_DT DATE
);

create table EMPLOYEE_AWARD
(
  AWARD_ID INT,
  EMPLOYEE_ID INT,
  AWARD_NAME VARCHAR(100),
  LAST_UPDATED_BY VARCHAR(200),
  LAST_UPDATED_DT DATE
);

create table EMPLOYEE_ADDRESS
(
  ADDRESS_ID INT,
  EMPLOYEE_ID INT,
  ADDRESS VARCHAR(100),
  LAST_UPDATED_BY VARCHAR(200),
  LAST_UPDATED_DT DATE
);

为了进一步解释,如果经理上周在EMPLOYEE表中添加了一条员工记录,一周后又添加了一个 EMPLOYEE_AWARD,我想检索最近的值LAST_UPDATE_DT以及相应的LAST_UPDATED_BY值。

简单地说,我想确定谁对员工记录进行了最新更新(跨越多个表。

我试图将所有这些表联合在一起并选择max(LAST_UPDATED_DT),但是我无法弄清楚如何获得正确的值LAST_UPDATED_BY

这是我尝试的 SQL:

select employee_id, max(last_updated_dt), last_updated_by from 
(
select employee_id, last_updated_dt, last_updated_by from 

EMPLOYEE
UNION
select employee_id, last_updated_dt, last_updated_by from 

EMPLOYEE_AWARD
UNION
select employee_id, last_updated_dt, last_updated_by from 

EMPLOYEE_ADDRESS
)
latest
where employee_id = 1
group by employee_id;

我还创建了一个 SQL Fiddle 来演示我的问题:

http://sqlfiddle.com/#!2/3b0e2/4

我很感激任何帮助。

4

2 回答 2

3

我有一个解决方案,但它很丑陋:

  1. UNION所有employee_ids,last_updated_dt,last_updated_by
  2. 使用分析函数按 last_updated_dt 排序
  3. 过滤掉最新的变化

.

SELECT employee_id, last_updated_dt, last_updated_by
  FROM (
        SELECT employee_id, last_updated_dt, last_updated_by, 
                row_number() OVER (
                  PARTITION BY employee_id 
                  ORDER BY last_updated_dt DESC) AS rn
          FROM (
                SELECT employee_id, last_updated_dt, last_updated_by 
                  FROM EMPLOYEE 
                 UNION ALL
                SELECT employee_id, last_updated_dt, last_updated_by 
                  FROM EMPLOYEE_AWARD
                 UNION ALL
                SELECT employee_id, last_updated_dt, last_updated_by 
                  FROM EMPLOYEE_ADDRESS
               )
       )
  WHERE rn=1;
于 2013-06-27T11:20:41.183 回答
2

我认为您可以将它们合并在一起,然后按 last_updated_dt 降序排列输出,并将输出限制为 1。

SELECT employee_id,
       last_updated_dt, 
       last_updated_by
  FROM (SELECT employee_id, last_updated_dt, last_updated_by 
          FROM employee
        UNION
        SELECT employee_id, last_updated_dt, last_updated_by 
          FROM employee_award
        UNION
        SELECT employee_id, last_updated_dt, last_updated_by 
          FROM employee_address
       ) last
 WHERE employee_id = 1
 ORDER BY last_updated_dt DESC
 LIMIT 1

为了提高效率,您可能希望将条件放在 UNION 子查询中。

SELECT employee_id,
       last_updated_dt, 
       last_updated_by
  FROM (SELECT employee_id, last_updated_dt, last_updated_by 
          FROM employee
         WHERE employee_id = 1
        UNION
        SELECT employee_id, last_updated_dt, last_updated_by 
          FROM employee_award
         WHERE employee_id = 1
        UNION
        SELECT employee_id, last_updated_dt, last_updated_by 
          FROM employee_address
         WHERE employee_id = 1
       ) last
 ORDER BY last_updated_dt DESC
 LIMIT 1

正如评论中正确指出的那样,上述解决方案仅适用于 MySQL,不适用于 Oracle。这是一个应该在 Oracle 中工作的版本。

SELECT DISTINCT employee_id,
                FIRST_VALUE(last_updated_dt) OVER (ORDER BY last_updated_dt DESC), 
                FIRST_VALUE(last_updated_by) OVER (ORDER BY last_updated_dt DESC)
  FROM (SELECT employee_id, last_updated_dt, last_updated_by 
          FROM employee
         WHERE employee_id = 1
        UNION
        SELECT employee_id, last_updated_dt, last_updated_by 
          FROM employee_award
         WHERE employee_id = 1
        UNION
        SELECT employee_id, last_updated_dt, last_updated_by 
          FROM employee_address
         WHERE employee_id = 1
       )
于 2013-06-27T11:19:48.700 回答