Teradata更新

时间:2015-04-06 12:22:24

标签: teradata

我的表中有以下数据:

eff_dt      end_dt      type_cd status
1-Jan-14    5-Jan-14    AAA     0
5-Jan-14    7-Jan-14    null    1
7-Jan-14    10-Jan-14   null    1
10-Jan-14   15-Jan-14   BBB     0
15-Jan-14   21-Jan-14   null    1
21-Jan-14   25-Jan-14   null    1
25-Jan-14   30-Jan-14   CCC     0

我想使用自联接更新数据。

更新表后应如下所示:

eff_dt      end_dt  type_cd status
1-Jan-14    5-Jan-14    AAA 0
5-Jan-14    7-Jan-14    AAA 1
7-Jan-14    10-Jan-14   AAA 1
10-Jan-14   15-Jan-14   BBB 0
15-Jan-14   21-Jan-14   BBB 1
21-Jan-14   25-Jan-14   BBB 1
25-Jan-14   30-Jan-14   CCC 0

请帮我解决teradata中的更新查询?

4 个答案:

答案 0 :(得分:1)

eff_dt      end_dt      type_cd status
1-Jan-14    5-Jan-14    AAA     0
5-Jan-14    7-Jan-14    null    1
7-Jan-14    10-Jan-14   null    1
10-Jan-14   15-Jan-14   BBB     0
15-Jan-14   21-Jan-14   null    1
21-Jan-14   25-Jan-14   null    1
25-Jan-14   30-Jan-14   CCC     0

根据上述数据,我们可以使用状态和日期自行加入。 第一行的end_dt基本上是第二行的eff_dt。

UPDATE A
FROM DB.TABLEA AS A, DB.TABLEA AS B
SET type_cd = B.type_cd
WHERE A.eff_dt = B.end_dt
and A.status = 1;

再次执行相同的更新以更新第3行状态。 如果没有。行是可变的,那么你将不得不修改查询。

答案 1 :(得分:0)

以下内容应该为您解决问题:

SELECT 
    t1.eff_dt, t1.end_dt, t2.type_cd, t1.status
FROM 
    yourtable t1
    LEFT OUTER JOIN (SELECT * FROM yourtable WHERE status = 0) t2 ON t1.end_dt >= t2.end_dt
QUALIFY ROW_NUMBER() OVER (PARTITION BY t1.end_dt ORDER BY t2.end_dt DESC) = 1

这会将您的表格加入到您的表格版本中,其中只有status=0个记录,因为这些记录是非空type_cd的记录。它在日期中加入查找具有type_cd并且end_dt小于当前记录end_dt的任何记录。

最后的QUALIFY窗口函数会查找type_cd具有最高end_dt的记录。这里的缺点是你的表越大,你在连接中产生的记录就越多,所以你的中间结果会大幅增长。您的结果将是正确的,但您将占用越来越多的假脱机空间。

如果您在此查询中发现难以理解窗口函数,请尝试在不使用SELECT *的情况下运行查询。您可以更轻松地完成QUALIFY逻辑。

答案 2 :(得分:0)

create table sample_1
(
eff_dt date,
end_dt date,
type_cd varchar(4)
,status int
);
insert into sample_1(date '2014-01-01',date '2014-01-05','aaa',0);
insert into sample_1(date '2014-01-05',date '2014-01-07',null,1);
insert into sample_1(date '2014-01-07',date '2014-01-10',null,1);
insert into sample_1(date '2014-01-10',date '2014-01-15','bbb',0);
insert into sample_1(date '2014-01-15',date '2014-01-21',null,1);
insert into sample_1(date '2014-01-21',date '2014-01-25',null,1);
insert into sample_1(date '2014-01-25',date '2014-01-30','ccc',0);

upd  tgt
from sample_1 tgt
, (
sel tgt.eff_dt,tgt.end_dt,lkp.type_cd,tgt.status
from sample_1 tgt,
(
sel tgt.*,max(eff_dt) over (order by eff_dt asc rows between 1 following and 1 following ) eff_dt1
from sample_1 tgt
where status=0 --type_cd is not null
) lkp
where tgt.eff_dt between lkp.eff_dt and coalesce  (eff_dt1,date '9999-12-31')
and coalesce ( tgt.type_cd,lkp.type_cd) =lkp.type_cd
) lkp
set type_cd=lkp.type_cd
where tgt.eff_dt=lkp.eff_dt 

答案 3 :(得分:0)

填充这些NULL对于LAST_VALUE来说是一项简单的任务:

UPDATE tgt
FROM mytable tgt
,(
   SEL eff_dt,
      Last_Value(type_cd IGNORE NULLS) 
      Over (ORDER BY eff_dt) AS last_cd
   FROM mytable
   QUALIFY type_cd IS NULL
 ) AS src   
SET type_cd = src.last_cd
WHERE tgt.eff_dt= src.eff_dt 

假设这只是一个例子,你必须为一组行做这个,你最好使用MERGE,永远不会慢,但可能会更快:

MERGE INTO mytable AS tgt
USING
 (
   SEL eff_dt,
      Last_Value(type_cd IGNORE NULLS) 
      Over (ORDER BY eff_dt) AS last_cd
   FROM mytable
   QUALIFY type_cd IS NULL
 ) AS src   
-- ON must include at least all (P)PI columns of the target table
ON tgt.eff_dt = src.eff_dt
WHEN MATCHED THEN
   UPDATE SET type_cd = src.last_cd