-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 的特性。

4

1 回答 1

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

一个用于测试的 SQLFiddle

编辑:既然你问了,这是一个使用的版本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;

另一个 SQLfiddle

于 2013-02-26T21:26:35.823 回答