2013-02-26 67 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