Home > database >  Query to create multiple equal records of volume distribution using duration (in terms of months)
Query to create multiple equal records of volume distribution using duration (in terms of months)

Time:08-19

Input Output ResultsHope you are doing good.

I am stuck in a requirement where I need to have records distributed into multiple records based on the duration I get it from a linking table.

Suppose I have a volume of 100 and duration I am getting is 20 months linking table then my output should have 20 records of each 5(100/20). Could you please help me with the query how to do this SQL.

CodePudding user response:

The WITH clause is here just to generate some sample data and, as such, it is not a part of the answer.
You can join the tables ON PRODUCT columns, limit the iterations using LEVEL <= DURATION, group the data and show the amount either as Min, Max or Avg of COST/DURATION rounded to two decimals. I put all of the data in the select list. Here is the complete code with the result. Regards...

 WITH
    t_duration AS
        (
            Select 'A' "PRODUCT", 10 "DURATION" From Dual Union All
            Select 'B' "PRODUCT",  6 "DURATION" From Dual Union All
            Select 'C' "PRODUCT",  4 "DURATION" From Dual 
        ),
    t_cost AS
        (
            Select 'A' "PRODUCT", 100 "COST" From Dual Union All
            Select 'B' "PRODUCT",  50 "COST" From Dual Union All
            Select 'C' "PRODUCT",  40 "COST" From Dual 
        )
SELECT
    LEVEL "MONTH_ORDER_NUMBER",
    d.PRODUCT "PRODUCT",
    d.DURATION "DURATION",
    c.COST "COST",
    Round(Avg(c.COST / d.DURATION), 2) "AVG_MONTHLY_AMOUNT",
    Round(Max(c.COST / d.DURATION), 2) "MAX_MONTHLY_AMOUNT",
    Round(Min(c.COST / d.DURATION), 2) "MIN_MONTHLY_AMOUNT"
FROM
    t_duration d
INNER JOIN
    t_cost c ON(c.PRODUCT = d.PRODUCT)
CONNECT BY LEVEL <= d.DURATION
GROUP BY 
    d.PRODUCT, d.DURATION, c.COST, LEVEL
ORDER BY 
    d.PRODUCT, LEVEL
--  
--  R e s u l t
--  
--  MONTH_ORDER_NUMBER PRODUCT   DURATION       COST AVG_MONTHLY_AMOUNT MAX_MONTHLY_AMOUNT MIN_MONTHLY_AMOUNT
--  ------------------ ------- ---------- ---------- ------------------ ------------------ ------------------
--                   1 A               10        100                 10                 10                 10 
--                   2 A               10        100                 10                 10                 10 
--                   3 A               10        100                 10                 10                 10 
--                   4 A               10        100                 10                 10                 10 
--                   5 A               10        100                 10                 10                 10 
--                   6 A               10        100                 10                 10                 10 
--                   7 A               10        100                 10                 10                 10 
--                   8 A               10        100                 10                 10                 10 
--                   9 A               10        100                 10                 10                 10 
--                  10 A               10        100                 10                 10                 10 
--                   1 B                6         50               8.33               8.33               8.33 
--                   2 B                6         50               8.33               8.33               8.33 
--                   3 B                6         50               8.33               8.33               8.33 
--                   4 B                6         50               8.33               8.33               8.33 
--                   5 B                6         50               8.33               8.33               8.33 
--                   6 B                6         50               8.33               8.33               8.33 
--                   1 C                4         40                 10                 10                 10 
--                   2 C                4         40                 10                 10                 10 
--                   3 C                4         40                 10                 10                 10 
--                   4 C                4         40                 10                 10                 10

CodePudding user response:

That looks as if ntile would do the job (at least, that's how I understood the question).

Here's a table with 100 rows (that's your "volume of 100").

SQL> create table test (id) as
  2  select level from dual connect by level <= 100;

Table created.

You'd then pass 20 (that's "duration of 20 months") to ntile and get the result - see the grp column, having 20 groups, each of them having 5 rows:

SQL> select id, ntile(20) over (order by id) grp
  2  from test
  3  order by id;

        ID        GRP
---------- ----------
         1          1
         2          1
         3          1
         4          1
         5          1
         6          2
         7          2
         8          2
         9          2
        10          2
        11          3
        12          3
        13          3
        14          3
        15          3
   <snip>
        91         19
        92         19
        93         19
        94         19
        95         19
        96         20
        97         20
        98         20
        99         20
       100         20

100 rows selected.

SQL>

[EDIT, based on new information]

With sample tables you posted:

SQL> with
  2  duration (product, duration) as
  3    (select 'A', 10 from dual union all
  4     select 'B', 6  from dual union all
  5     select 'C', 4  from dual
  6    ),
  7  cost (product, cost) as
  8    (select 'A', 100 from dual union all
  9     select 'B', 50  from dual union all
 10     select 'C', 40  from dual
 11    )

query would look like this:

 12  select d.product,
 13         c.cost / d.duration as amount
 14  from duration d join cost c on c.product = d.product
 15    cross join table(cast(multiset(select level from dual
 16                                   connect by level <= d.duration
 17                                  ) as sys.odcinumberlist))
 18  order by d.product;

PRODUCT        AMOUNT
---------- ----------
A                  10
A                  10
A                  10
A                  10
A                  10
A                  10
A                  10
A                  10
A                  10
A                  10
B          8,33333333
B          8,33333333
B          8,33333333
B          8,33333333
B          8,33333333
B          8,33333333
C                  10
C                  10
C                  10
C                  10

20 rows selected.

SQL>
  • Related