Warm tip: This article is reproduced from serverfault.com, please click

Sql to split row to multiple rows based on a fixed value of multiple columns

发布于 2020-11-28 18:22:00
create table qty_split 
(
    order varchar2(4), 
    article_code varchar2(4), 
    size_1 number(3,0), 
    size_2 number(3,0), 
    size_3 number(3,0)
); 

insert into qty_split values ('a001', '1111', 123, 165, 85);

commit;


select * from qty_split;

'a001'  '1111'  123  165  85

Now I need an Oracle SQL query to split the above row based on upper limit of quantity 99 on columns size_1, size_2 and size_3.

So expected result would be:

'a001'  '1111'  99  99  85
'a001'  '1111'   24  66  0
Questioner
Subrata Dutta
Viewed
0
MT0 2020-11-29 04:10:06

You can use a recursive sub-query factoring clause to split the data for any amount:

WITH data ( "ORDER", article, size_1, size_2, size_3 ) AS (
  SELECT * FROM qty_split
UNION ALL
  SELECT "ORDER",
         article,
         GREATEST( size_1 - 99, 0 ),
         GREATEST( size_2 - 99, 0 ),
         GREATEST( size_3 - 99, 0 )
  FROM   data
  WHERE  size_1 > 99
  OR     size_2 > 99
  OR     size_3 > 99
)
SELECT "ORDER",
       article,
       LEAST( size_1, 99 ) AS size_1,
       LEAST( size_2, 99 ) AS size_2,
       LEAST( size_3, 99 ) AS size_3
FROM   data
ORDER BY
       "ORDER",
       article,
       ROWNUM;

Which, for the sample data:

create table qty_split (
  "ORDER" varchar2(4),
  article_code varchar2(4), 
  size_1 number(3,0),
  size_2 number(3,0),
  size_3 number(3,0)
);

insert into qty_split 
SELECT 'a001', '1111', 123, 165, 85 FROM DUAL UNION ALL
SELECT 'b002', '2222', 312, 45, 17 FROM DUAL UNION ALL
SELECT 'c003', '3333', 0, 0, 417 FROM DUAL;

Outputs:

ORDER | ARTICLE | SIZE_1 | SIZE_2 | SIZE_3
:---- | :------ | -----: | -----: | -----:
a001  | 1111    |     99 |     99 |     85
a001  | 1111    |     24 |     66 |      0
b002  | 2222    |     99 |     45 |     17
b002  | 2222    |     99 |      0 |      0
b002  | 2222    |     99 |      0 |      0
b002  | 2222    |     15 |      0 |      0
c003  | 3333    |      0 |      0 |     99
c003  | 3333    |      0 |      0 |     99
c003  | 3333    |      0 |      0 |     99
c003  | 3333    |      0 |      0 |     99
c003  | 3333    |      0 |      0 |     21

db<>fiddle here