1

Oracle データベースに、従業員の記録に関連するいくつかのテーブルがあります。これらの各テーブルにはEMPLOYEE_IDLAST_UPDATED_DTとの 3 つの同様の列が含まれていますLAST_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先週テーブルに従業員レコードを追加し、1 週間後に 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

コメントで正しく指摘されているように、上記のソリューションは Oracle ではなく MySQL でのみ機能します。これは、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 に答える