如何在 sql 中进行自连接和创建新列

How to do self join and create a new column in sql

我在 运行 多次查询后从一个巨大的数据库中创建了一个 table,示例如下:

communication_day | comid | person_id | area_id | w_id  
20-MAR-17 03:45 | 21 | xyz1 | y123 | S1
20-MAR-17 07:45 | 21 | xyz1 | y142 | S2
14-MAR-17 07:45 | 41 | xyz1 | y153 | S1
14-MAR-17 09:00 | 41 | xyz1 | y123 | S3
30-MAR-17 09:00 | 88 | abc1 | y180 | D1
30-MAR-17 11:00 | 88 | abc1 | y181 | D2

基本上,一个人(由 person_id 表示)进来并请求更改其区域 ID,这可以由一个人多次完成。每当一个人提出这个要求时,他就会得到一个 comid。因此,就像上面的示例 person_id = xyz1 首先请求从 y153 更改为 y123 然后在 3 月 20 日,请求从 y123 更改为y142

我想在此 table 中创建一个名为 old_w_id 的新列,这样对于每个更改请求(每个 comid),它都包含旧值。例如上面的示例:

old_w_id
S1
S1
S1
S1
D1
D1

在请求进入该 comid 的情况下,old_w_id 只能具有相同的值。只有在更改请求生效的地方,old_w_id 应该具有以前的值。

知道我该怎么做吗??提前致谢!!

更新:每个 comid 可能不一定有 2 行,即,一个人可能已经请求更改但它可能尚未得到确认(此时只为该 comid 提供一行)。

是的,我当然可以解释。 partition by 子句告诉分析函数按您指定的列进行分区计算,在我们的例子中是 person_id,否则 lag 函数将对您返回的行集中的所有行起作用。而且我还会删除第一条记录的默认值,我会将 lag(w_id, 1, w_id) 更改为 lag(w_id, 1) 显示 null 更正确,因为它没有滞后 w_id .像这样。

with my_table as
 (

  select to_date('20-MAR-17 03:45', 'DD-MON-YY HH24:MI',
                   'nls_date_language=english') as communication_day, 21 as comid,
          'xyz1' as person_id, 'y123' as area_id, 'S1' w_id
    from dual
  union all

  select to_date('20-MAR-17 03:45', 'DD-MON-YY HH24:MI',
                   'nls_date_language=english') as communication_day, 21 as comid,
          'xyz1' as person_id, 'y142' as area_id, 'S2' w_id
    from dual
  union all
  select to_date('14-MAR-17 07:45', 'DD-MON-YY HH24:MI',
                   'nls_date_language=english') as communication_day, 41 as comid,
          'xyz1' as person_id, 'y153' as area_id, 'S1' w_id
    from dual
  union all
  select to_date('14-MAR-17 09:00', 'DD-MON-YY HH24:MI',
                   'nls_date_language=english') as communication_day, 41 as comid,
          'xyz1' as person_id, 'y123' as area_id, 'S3' w_id
    from dual
  union all
  select to_date('30-MAR-17 09:05', 'DD-MON-YY HH24:MI',
                   'nls_date_language=english') as communication_day, 88 as comid,
          'abc1' as person_id, 'y180' as area_id, 'D1' w_id
    from dual
  union all
  select to_date('30-MAR-17 11:00', 'DD-MON-YY HH24:MI',
                   'nls_date_language=english') as communication_day, 88 as comid,
          'abc1' as person_id, 'y181' as area_id, 'D2' w_id
    from dual)

select t.*,
       lag(w_id, 1) over(partition by person_id, comid order by communication_day) as old_w_id
  from my_table t

输出将是

    COMMUNICATION_DAY   COMID   PERSON_ID   AREA_ID W_ID    OLD_W_ID
1   30/03/17 09:05:00   88      abc1        y180    D1  
2   30/03/17 11:00:00   88      abc1        y181    D2      D1
3   14/03/17 07:45:00   41      xyz1        y153    S1  
4   14/03/17 09:00:00   41      xyz1        y123    S3      S1
5   20/03/17 03:45:00   21      xyz1        y123    S1      
6   20/03/17 03:45:00   21      xyz1        y142    S2      S1