【问题标题】:Split data for equal group (PL/SQL, SQL)为相等组拆分数据(PL/SQL、SQL)
【发布时间】:2019-08-12 09:59:24
【问题描述】:

我有多个 id:

Select count(*) Into count_id From table_I;--4

我知道我总共有total_user = 109(记录数)。所以我想把它分成相等的组:

Select round(count(*)/count_user,0) Into mapUser From table_U;

所以我有4 group。在first three will be 27last should be 28 用户中。

现在我想for each group 分配唯一ID。

set serveroutput on 
declare 
      CURSOR cur IS Select * From table_U FOR UPDATE OF USER_ID;
      mapUser NUMBER;
      l_rec table_U%rowtype;
      x_mapUser Number := 0;--number between 0-27
      c_obj_id NUMBER := 1;
      count_id NUMBER := 0;

      type T1 is table of number(10) index by binary_integer;
      V1 T1;    

begin
     Select count(*) Into count_id From table_I;--count_id = 4
     Select round(count(*)/count_id,0) Into mapUser From table_U; --mapUser = 27

     SELECT id BULK COLLECT INTO V1 FROM table_I;--it's 4 id (id_1, id_2, id_3, id_4)

    OPEN cur;
        LOOP FETCH cur INTO l_rec;
         EXIT WHEN cur%notfound;

           IF x_mapUser > mapUser Then --0-27 > 27
                x_mapUser := 1;                   
                c_obj_id := c_obj_id +1;--next value from V1
           End if;

          UPDATE table_U SET USER_ID = V1(c_obj_id) WHERE CURRENT OF cur;

         x_mapUser := x_mapUser +1;

        END LOOP;
       CLOSE cur;        
end;

但我不知道如何更改我的IFcur 的最后一个值分配以及id_4。我在这里做错了:/

【问题讨论】:

  • 样本数据和期望的结果真的很有帮助。

标签: sql oracle plsql cursor bulk


【解决方案1】:

这对我有用:

merge into table_u a
using (select rd, i.id
         from (select u.rowid rd, cnt - mod(rownum-1, cnt) rn 
                 from table_u u, (select count(1) cnt from table_i) ) u
         join (select row_number() over( order by id) rn, id from table_i) i using (rn)) b
on (a.rowid = b.rd)         
when matched then update set a.user_id = b.id

我的测试表:

create table table_i as (
  select level*10 id from dual connect by level <= 4);

create table table_u as (
  select cast(null as number(3)) user_id, level id from dual connect by level <= 109);

第二个表中的最高值被分配了 28 次,其他 27 次。因为我用过

cnt - mod(rownum-1, cnt) rn

计算加入列。我不知道这对你是否重要。 :) 此解决方案的基础是 mod(),它允许我们在 1cnt 之间循环(在本例中为 4)。

您可以在 PLSQL 中执行此操作,但如果可能,SQL 解决方案通常更快且更受欢迎。

【讨论】:

  • 思考 - 我刚刚测试了您的代码,并且在我的网站上运行正常,太好了,感谢您的帮助!
【解决方案2】:

我会使用ntile():

select u.*, ntile(4) over (order by user_id) as grp
from table_u u;

我不知道你想要什么顺序,如果有的话。如果您愿意,可以使用随机数。

如果要枚举每个组中的值,请使用子查询:

select u.*, row_number() over (partition by grp order by grp) as seqnum
from (select u.*, ntile(4) over (order by user_id) as grp
      from table_u u
     ) u;

【讨论】:

  • 好的,现在如何从 table_u 更新列 (col1)?就像 group_ 1 有 id_1,group_ 2 有 id_2 .....(id from table_I)
【解决方案3】:

我发现了错误,并用我的 PL/SQL 代码也这样做了:

...
x_mapUser Number := 0
...
OPEN cur;
 LOOP FETCH cur INTO l_rec;
  EXIT WHEN cur%notfound;
     UPDATE table_U SET USER_ID = V1(c_obj_id) WHERE CURRENT OF cur;

     IF x_mapUser > mapUser-1 AND c_obj_id < count_id Then
            x_mapUser := 0;
            c_obj_id := c_obj_id +1;
     End if;

 x_mapUser := x_mapUser +1;

 END LOOP;
CLOSE cur;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-07
    • 2016-06-10
    • 2014-08-25
    • 2015-06-08
    • 1970-01-01
    • 2015-02-02
    • 1970-01-01
    相关资源
    最近更新 更多