(Oracle)如何对行进行分组以进行分页

kei*_*iko 6 sql oracle pagination oracle10g

我有一个输出类似于此的表(尽管有数千个):

     EMPNO ENAME      TRANDATE      AMT
---------- ---------- --------- -------
       100 Alison     21-MAR-96   45000
       100 Alison     12-DEC-78   23000
       100 Alison     24-OCT-82   11000
       101 Linda      15-JAN-84   16000
       101 Linda      30-JUL-87   17000
       102 Celia      31-DEC-90   78000
       102 Celia      17-SEP-96   21000
       103 James      21-MAR-96   45000
       103 James      12-DEC-78   23000
       103 James      24-OCT-82   11000
       104 Robert     15-JAN-84   16000
       104 Robert     30-JUL-87   17000
Run Code Online (Sandbox Code Playgroud)

我想要的输出类似于:

     EMPNO ENAME      TRANDATE      AMT PAGE
---------- ---------- --------- ------- ----
       100 Alison     21-MAR-96   45000    1
       100 Alison     12-DEC-78   23000    1
       100 Alison     24-OCT-82   11000    1
       101 Linda      15-JAN-84   16000    2
       101 Linda      30-JUL-87   17000    2
       102 Celia      31-DEC-90   78000    2
       102 Celia      17-SEP-96   21000    2
       103 James      21-MAR-96   45000    3
       104 Robert     12-DEC-78   23000    4
       104 Robert     24-OCT-82   11000    4
       104 Robert     15-JAN-84   16000    4
       104 Robert     30-JUL-87   17000    4
Run Code Online (Sandbox Code Playgroud)

基本上,它应该插入一个新字段来标识它所属的页面.分页符基于行.并且,就像在EMPNO中"保持在一起"一样,当行无法添加下一个EMPNO批次时,它会向PAGE添加1.这是Excel限制,因为Excel在单个工作表中不允许超过65000行(或左右).在样本的情况下,它只有4行.限制数是静态的.

Gar*_*ers 2

ThinkJet 是对的,其他一些答案不能满足“保持在一起”的要求。不过我认为这可以在不诉诸用户定义的聚合的情况下完成。

样本数据

create table test (empno number, ename varchar2(20), trandate date, amt number);
insert into test values (100, 'Alison'   ,  to_date('21-MAR-1996') ,   45000);
insert into test values (100, 'Alison'   ,  to_date('12-DEC-1978') ,   23000);
insert into test values (100, 'Alison'   ,  to_date('24-OCT-1982') ,   11000);
insert into test values (101, 'Linda'    ,  to_date('15-JAN-1984') ,   16000);
insert into test values (101, 'Linda'    ,  to_date('30-JUL-1987') ,   17000);
insert into test values (102, 'Celia'    ,  to_date('31-DEC-1990') ,   78000);
insert into test values (102, 'Celia'    ,  to_date('17-SEP-1996') ,   21000);
insert into test values (103, 'James'    ,  to_date('21-MAR-1996') ,   45000);
insert into test values (103, 'James'    ,  to_date('12-DEC-1978') ,   23000);
insert into test values (103, 'James'    ,  to_date('24-OCT-1982') ,   11000);
insert into test values (104, 'Robert'   ,  to_date('15-JAN-1984') ,   16000);
insert into test values (104, 'Robert'   ,  to_date('30-JUL-1987') ,   17000);
Run Code Online (Sandbox Code Playgroud)

现在,确定每个 empno 段的结束行(使用 RANK 查找开头,使用 COUNT..PARTITION BY 查找段中的编号)。

然后使用 APC 解决方案中的 ceil/4 将它们分组到“页面”中。同样,正如 ThinkJet 所指出的,规范中存在一个问题,因为它不能满足 empno“保持在一起”段中的记录多于页面所能容纳的情况的情况。

select empno, ename,
       ceil((rank() over (order by empno) +
         count(1) over (partition by empno))/6) as chunk
from test
order by 1;
Run Code Online (Sandbox Code Playgroud)

正如 ThinkJet 所指出的,该解决方案并非万无一失。

drop table test purge;

create table test (empno number, ename varchar2(20), trandate date, amt number);
declare
    cursor csr_name is
    select rownum emp_id, 
             decode(rownum,1,'Alan',2,'Brian',3,'Clare',4,'David',5,'Edgar',
             6,'Fred',7,'Greg',8,'Harry',9,'Imran',10,'John',
             11,'Kevin',12,'Lewis',13,'Morris',14,'Nigel',15,'Oliver',
             16,'Peter',17,'Quentin',18,'Richard',19,'Simon',20,'Terry',
             21,'Uther',22,'Victor',23,'Wally',24,'Xander',
             25,'Yasmin',26,'Zac') emp_name
    from dual connect by level <= 26;
begin
  for c_name in csr_name loop
    for i in 1..11 loop
       insert into test values 
           (c_name.emp_id, c_name.emp_name, (date '2010-01-01') + i,
             to_char(sysdate,'SS') * 1000);
    end loop;
  end loop;
end;
/

select chunk, count(*)
from
  (select empno, ename,
       ceil((rank() over (order by empno) +
         count(1) over (partition by empno))/25) as chunk
  from test)
group by chunk
order by chunk
;
Run Code Online (Sandbox Code Playgroud)

因此,当块大小为 25 且组大小为 11 时,尽管有 25 人的限制,但我们仍能在块中容纳 33 人。大块大小和小组应该会使这种情况很少发生,但您需要留出一些余地。因此,可以将块设置为 65,000,而不是一直设置为 65,536。