偏移和分组

时间:2016-01-07 10:57:12

标签: oracle11g plsqldeveloper

我有2列'a','b'。列有20条记录,我想从列'a'中选择前10条记录,并将列'b'更新为'c' 然后从a中选择接下来的10条记录,并将'b'列更新为'd'。? 我怎么能这样做?是否可以使用off set? 我试过分区,但它不是很有帮助,然后我想到了偏移但是我如何循环选择10条记录一次并更新值?

A B
1
2
3
4
5
6

我想通过C和下一个3记录和更新B作为D记录第一个和第二个B记录三个记录

A  B
1  C
2  C
3  C
4  D
5  D
6  D

1 个答案:

答案 0 :(得分:0)

根据您想要处理奇数行的情况(您想要更多C或更多D' s),您可以使用以下两个合并语句之一来更新行:

更多Ds:

merge into t1 tgt
using (select a,
              case when rn/cnt <= 0.5 then 'C'
                   else 'D'
              end new_b
       from   (select a,
                      row_number() over (order by a) rn,
                      count(*) over () cnt
               from   t1)) src
on (tgt.a = src.a)
when matched then
update set tgt.b = src.new_b;

更多Cs:

merge into t1 tgt
using (select a,
              case when rn/decode(mod(cnt, 2), 0, cnt, 1, cnt + 1) <= 0.5 then 'C'
                   else 'D'
              end new_b
       from   (select a,
                      row_number() over (order by a) rn,
                      count(*) over () cnt
               from   t1)) src
on (tgt.a = src.a)
when matched then
update set tgt.b = src.new_b;

请参阅下文,了解我用于测试两个语句的完整脚本:

create table t1 as
select 1 a, cast(null as varchar2(2)) b from dual union all
select 2 a, null b from dual union all
select 3 a, null b from dual union all
select 4 a, null b from dual union all
select 5 a, null b from dual union all
select 6 a, null b from dual;

-- six rows, basic method - for odd rows, there will be a greater number of Ds

merge into t1 tgt
using (select a,
              case when rn/cnt <= 0.5 then 'C'
                   else 'D'
              end new_b
       from   (select a,
                      row_number() over (order by a) rn,
                      count(*) over () cnt
               from   t1)) src
on (tgt.a = src.a)
when matched then
update set tgt.b = src.new_b;

commit;

select * from t1;

         A B 
---------- --
         1 C 
         2 C 
         3 C 
         4 D 
         5 D 
         6 D 

-- six rows, extended method - for odd rows, there will be a greater number of Cs

merge into t1 tgt
using (select a,
              case when rn/decode(mod(cnt, 2), 0, cnt, 1, cnt + 1) <= 0.5 then 'C'
                   else 'D'
              end new_b
       from   (select a,
                      row_number() over (order by a) rn,
                      count(*) over () cnt
               from   t1)) src
on (tgt.a = src.a)
when matched then
update set tgt.b = src.new_b;

commit;

select * from t1;

         A B 
---------- --
         1 C 
         2 C 
         3 C 
         4 D 
         5 D 
         6 D 


insert into t1 (a, b)
values (7, null);

commit;

-- seven rows, basic method - for odd rows, there will be a greater number of Ds

merge into t1 tgt
using (select a,
              case when rn/cnt <= 0.5 then 'C'
                   else 'D'
              end new_b
       from   (select a,
                      row_number() over (order by a) rn,
                      count(*) over () cnt
               from   t1)) src
on (tgt.a = src.a)
when matched then
update set tgt.b = src.new_b;

select * from t1;

         A B 
---------- --
         1 C 
         2 C 
         3 C 
         4 D 
         5 D 
         6 D 
         7 D 

-- seven rows, extended method - for odd rows, there will be a greater number of Cs

merge into t1 tgt
using (select a,
              case when rn/decode(mod(cnt, 2), 0, cnt, 1, cnt + 1) <= 0.5 then 'C'
                   else 'D'
              end new_b
       from   (select a,
                      row_number() over (order by a) rn,
                      count(*) over () cnt
               from   t1)) src
on (tgt.a = src.a)
when matched then
update set tgt.b = src.new_b;

select * from t1;

         A B 
---------- --
         1 C 
         2 C 
         3 C 
         4 C 
         5 D 
         6 D 
         7 D 

drop table t1;