I'm assuming data that looks something like this:
| CUSTOMER | SALE | MARGIN_PCT |
|----------|-------|------------|
| 1 | 10.12 | 2 |
| 1 | 12.99 | 39 |
| 1 | 20.95 | 16 |
| 1 | 80.00 | 18 |
| 2 | 94.99 | 17 |
| 2 | 92.98 | 70 |
First, we find which "bin" each transaction falls into:
select customer, sale, floor(margin_pct/5) as bin from sales
Then take those results and roll them up into bins per customer:
select customer, sum(sale) total_sales, bin
from
(select customer, sale, floor(margin_pct/5) as bin from sales) customer_bins
group by customer, bin
Finally, take those results and roll them up per customer:
select customer, group_concat(total_sales separator ', ')
from
(
select customer, sum(sale) total_sales, pct_group
from
(select customer, sale, floor(margin_pct/5) as bin from sales) customer_bins
group by customer, pct_group
) binned
group by customer
This gives
| CUSTOMER | BINNED_MARGINS |
|----------|----------------------|
| 1 | 100.95, 12.99, 10.12 |
| 2 | 94.99, 92.98 |
We are almost there, but clearly we have a big problem. Unless you can guarantee that you will always have records that fall into every bin, your results won't make much sense.
Unfortunately, MySQL doesn't offer an elegant solution to this. Your best option is to make a range table to join against. Simply:
| BIN |
|-----|
| 0 |
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
Finally, by joining against the bin
and customer
tables we can force values for all bins:
select customer, group_concat(total_sales separator ', ') as binned_margins
from
(
select customer, sum(sale) total_sales, bin
from
(
select customer, ifnull(sale, 0) sale, bin
from bin
inner join customer
left join (select customer, sale, floor(margin_pct/5) as bin from sales) customer_sale_bins
using(customer, bin)
order by customer, bin
) customer_bins
group by customer, bin
) binned
group by customer
Produces:
| CUSTOMER | BINNED_MARGINS |
|----------|----------------------------------------------------------------|
| 1 | 10.12, 0.00, 0.00, 100.95, 0.00, 0.00, 0.00, 12.99, 0.00, 0.00 |
| 2 | 0.00, 0.00, 0.00, 94.99, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00 |
SQL Fiddle