2013-02-26 66 views
-2

我有一個EMPLOYEE_AUDIT表像這樣甲骨文排差異

Employee_id Revision First_name Last_Name Gender Position 
    1   1  David  Hem  Male  Developer 
    1   2  David  Hem  Male  Manager 
    1   3  David  Alter  Male  Manager 
    2   1  Agatha  Christie Female Business Analyst 
    2   2  Agatha  Christie Female Group Manager 
    2   3  Agatha  Christie Female General Manager 

,我需要一個SQL查詢與輸出這樣的

Column_name employee_id Revision Old_Value   new_value 
    Position  1   2  Developer   Manager 
    Last_name  1   3  Hem    Alter 
    Position  2   2  Business Analyst Group Manager 
    Position  2   3  Group Manager  General Manager 

我們正在使用Oracle 10g,因此,請忽略11g特性。

+0

所以你想要一個函數,獲取最後一個比較的輸出並將其吐入一個表中? – Woot4Moo 2013-02-26 21:04:49

+0

你能爲此創建一個sql提琴:sqlfiddle.com – Woot4Moo 2013-02-26 21:07:23

+0

更喜歡一個查詢或函數什麼是有效的真的 – user1224036 2013-02-26 21:07:53

回答

1

不一定是最漂亮的SQL,但這會使用非常通用的CASE邏輯來實現。
由於它是一個審計表,它假定修訂中沒有差距來簡化事情。

SELECT 
CASE 
    WHEN ea1."First_name" <> ea2."First_name" THEN 'First_Name' 
    WHEN ea1."Last_Name" <> ea2."Last_Name" THEN 'Last_Name' 
    WHEN ea1."Gender"  <> ea2."Gender"  THEN 'Gender' 
    WHEN ea1."Position" <> ea2."Position" THEN 'Position' END "Column_name", 
ea2."Employee_id", ea2."Revision", 
CASE 
    WHEN ea1."First_name" <> ea2."First_name" THEN ea1."First_name" 
    WHEN ea1."Last_Name" <> ea2."Last_Name" THEN ea1."Last_Name" 
    WHEN ea1."Gender"  <> ea2."Gender"  THEN ea1."Gender" 
    WHEN ea1."Position" <> ea2."Position" THEN ea1."Position" END "Old_Value", 
CASE 
    WHEN ea1."First_name" <> ea2."First_name" THEN ea2."First_name" 
    WHEN ea1."Last_Name" <> ea2."Last_Name" THEN ea2."Last_Name" 
    WHEN ea1."Gender"  <> ea2."Gender"  THEN ea2."Gender" 
    WHEN ea1."Position" <> ea2."Position" THEN ea2."Position" END "New_Value" 
FROM EMPLOYEE_AUDIT ea1 
JOIN EMPLOYEE_AUDIT ea2 
    ON ea1."Employee_id" = ea2."Employee_id" 
    AND ea1."Revision" = ea2."Revision" -1 

An SQLFiddle to test with

編輯:既然你問了,這是一個使用LAG的版本,不是很大的改進;

WITH cte AS (
    SELECT "Employee_id", "Revision", "First_name" fn, "Last_Name" ln, 
    "Gender" g, "Position" p, 
    LAG("First_name", 1) OVER 
     (PARTITION BY "Employee_id" ORDER BY "Revision") fn2, 
    LAG("Last_Name", 1) OVER 
     (PARTITION BY "Employee_id" ORDER BY "Revision") ln2, 
    LAG("Gender", 1) OVER 
     (PARTITION BY "Employee_id" ORDER BY "Revision") g2, 
    LAG("Position",1) OVER 
     (PARTITION BY "Employee_id" ORDER BY "Revision") p2 
    FROM EMPLOYEE_AUDIT 
) 
SELECT 
CASE 
    WHEN fn <> fn2 THEN 'First_Name' WHEN ln <> ln2 THEN 'Last_Name' 
    WHEN g <> g2 THEN 'Gender' WHEN p <> p2 THEN 'Position' 
END "Column_name", "Employee_id", "Revision", 
CASE 
    WHEN fn <> fn2 THEN fn2 WHEN ln <> ln2 THEN ln2 
    WHEN g <> g2 THEN g2 WHEN p <> p2 THEN p2 
END "Old_Value", 
CASE 
    WHEN fn <> fn2 THEN fn WHEN ln <> ln2 THEN ln 
    WHEN g <> g2 THEN g WHEN p <> p2 THEN p 
END "New_Value" 
FROM cte 
WHERE fn2 IS NOT NULL; 

Another SQLfiddle

+0

我在想我們可以在這裏使用滯後嗎? – user1224036 2013-02-26 21:38:07

+0

@ user1224036你可以,但我不確定它會簡化聲明。您仍然需要以類似的方式進行比較,只有自加入部分會消失。 – 2013-02-26 21:44:10

+0

這樣的例子也會很有幫助 – user1224036 2013-02-26 21:52:37