如何在 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
我在 运行 多次查询后从一个巨大的数据库中创建了一个 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