简体   繁体   中英

How to categorize or divide total days proportionately to a specific category using SQL

Let say I have 65.52 days

And i want to divide this number into portion of 13.25 days so the output result would be like in cumulative

  • 13.25 days
  • 26.51 days
  • 39.77 days
  • 53.02 days
  • 65.52 days

Notice the categorization is cumulative from the divided value for example second value 26.51 days = 13.25 + 13.25 and third is 39.77 = 26.51 days + 13.25 days

However at the end the value fall exactly at the limit of the total days. Not exceed and it is not +13.25 anymore.

Item    Total Days  Divided     Categorized
Roc-1   65.52       13.26           13.26
                    13.26           26.51
                    13.26           39.77
                    13.26           53.02
                    12.50           65.52

You could join with a tally table or a subquery that gives a range of numbers.

For example :

SELECT 
t.Item, 
t.Days as `Total Days`, 
round(case when (n.n * t.Divider) > t.Days then t.Days - ((n.n-1) * t.Divider) else t.Divider end,2) as Divided, 
round(case when (n.n * t.Divider) > t.Days then t.Days else (n.n * t.Divider) end,2) as Categorized 
FROM (
  select 
  Item, 
  `Total Days` as Days, 
  13.26 as Divider 
  from YourDatabase.YourTable) t 
JOIN (
  SELECT (b.N * 10 + a.N + 1) as n 
  FROM 
  (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a ,
  (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b 
 ) n ON (n.n <= ceil(t.Days/t.Divider))

The example output used 13.26 instead of 13.25, so the former was used in the example.

Result:

Item    Total Days  Divided Categorized 
Roc-1   62.52       13.26   13.26   
Roc-1   62.52       13.26   26.52   
Roc-1   62.52       13.26   39.78   
Roc-1   62.52       13.26   53.04   
Roc-1   62.52       9.48    62.52   

Since roc-1 is mentioned in the question the split may have a relationship with the number of entries in a table for roc-1 so this might work

select t1.*,
        @rn:=@rn+1 rn,
        @maxrows maxrows,
        cast(
        case 
            when @rn <> @maxrows then @divided
            else 65.52 - (@divided * (@rn -1))
        end 
        as decimal(5,2))
         divided
        ,cast(
        case 
            when @rn <> @maxrows then   @cum_total:= @cum_total + @divided
            else @cum_total:=@cum_total + 65.52 - (@divided * (@rn -1))
         end 
         as decimal(5,2))
         cumtot

from  (select @divided:= 13.26,@cum_total:=0) d,
        (select @rn:=0) rn,
        (select @maxrows:= (select count(*) from table1 t where t.id = 'roc-1')) maxrows,
        table1 t1

+-------+------+---------+---------+--------+
| ID    | rn   | maxrows | divided | cumtot |
+-------+------+---------+---------+--------+
| roc-1 |    1 |       5 |   13.26 |  13.26 |
| roc-1 |    2 |       5 |   13.26 |  26.52 |
| roc-1 |    3 |       5 |   13.26 |  39.78 |
| roc-1 |    4 |       5 |   13.26 |  53.04 |
| roc-1 |    5 |       5 |   12.48 |  65.52 |
+-------+------+---------+---------+--------+

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM