JOIN表自己的SQL

时间:2016-07-20 09:00:09

标签: sql oracle join

让我们说例如我有表:

-----------------------------------------------
| id  | name | age | hair_color | delete_flag |
-----------------------------------------------
| 1   | Jhon | 20  | black      | 0           |
-----------------------------------------------

现在当一个属性被改变时,让我们说Jhon现在是21我们插入一个新的记录形式Jhon并且我们将之前的delete_flag设置为1.这是一个奇怪的工作流程但是我试图保持它的简单示例。

我的目标是找出Jhon的哪个属性发生了变化。在更复杂的问题版本中,当我们有一个Person表,Property_type表和Properties表时,在最后一个表中看起来像:

属性

-----------------------------------------------------------
| id | person_id | property_type_id | value | delete_flag |
-----------------------------------------------------------
| ....                                                    |
-----------------------------------------------------------

这里Jhon的所有道具都是不同的行,当Jhon例如改变他的头发颜色所有以前的道具(所有行有person_id = jhons_id)被设置为删除(delete_flag = 1)并且所有道具再次添加时只有差异:头发颜色道具不同(只有1行差异)。

现在我想知道哪个道具已被改变?他改变了头发的颜色,还是已经过了21年。我尝试使用属性和属性之间的某种JOIN来执行此操作,但没有设法获得结果。

PS:我无法添加像'changed'(0/1)这样的新列。

2 个答案:

答案 0 :(得分:2)

尝试使用windows函数lead / lag

表格

        ID NAME        AGE HAIR_                             DELETE_FLAG
---------- ---- ---------- ----- ---------------------------------------
         1 John         20 black                                       1
         2 John         21 black                                       0

select id, name, age, hair_color,
       case 
         when age <> prev_age then 'Age Changed'
         when hair_color <> prev_hair_color then 'Hair Changed'
         else 'Nothing Changes just Rearranges' end as changes,
         prev_age, prev_hair_color
  from (
  select id, name, age, hair_color, 
         lead(age) over (partition by name order by id desc) prev_age,
         lead(hair_color) over (partition by name order by id desc) prev_hair_color,
         delete_flag
    from t
  ) t1
  where delete_flag = 0;

<强> OUPUT

ID         NAME       AGE        HAIR_COLOR CHANGES     PREV_AGE   PREV_HAIR_COLOR             
2          John       21         black      Age Changed 20         black      

答案 1 :(得分:0)

我猜你在这个过程中为John分配了一个新的ID,因为你的目标似乎在​​某个点上有两条John记录(其中一条记录的delete_flag为true),那么你应该有另一种发现约翰的方法,我认为它是name列。

我有两种建议方法:

您可以在属性表中使用MINUS来查找旧约翰和新约翰之间已更改的属性:

SELECT prop_id
  FROM property
 WHERE person_id = oldJOHNid
MINUS
SELECT prop_id
  FROM property
 WHERE person_id = newJOHNid

在用户表中,您可以比较所有属性列,以查找所有新/旧记录或特定用户的差异

SELECT  TOLD.name, TOLD.id AS old_id, TNEW.id AS new_id,
       (CASE WHEN TOLD.age = TNEW.age THEN 'Age identical' ELSE 'Age Changed' END) age_status,
       ...
       (CASE WHEN TOLD.hair = TNEW.hair THEN 'Hair identical' ELSE 'Hair changed' END) hair_status
  FROM usertable  TOLD,
       usertable TNEW
 WHERE TOLD.name = TNEW.name
     AND TOLD.name='John' -- optional