Mysql查询通过查询生成'bin'ed和以及组中的其他聚合

时间:2014-03-14 19:42:14

标签: mysql group-by aggregate-functions

我想生成像

这样的结果集
 select 
  customer
  bin_sum(sales,margin_pct,0.5), 
  count(1) txns, 
  sum(sales) total_sales, 
  sum(margin) total margin
 from sales_txns
 group by customer

这样" bin_sum"将生成一个数组或csv_list,其中包含客户根据' bins'增量为5 pct。此列的输出将包含销售额的总和0-5%保证金,5-10%保证金,10-15%保证金等,以便此字段的输出

customer1|"0,0,234.24,2632.45,4567.50,0,0,0,0,0,0,0"|37|783736.429|22443.23
customer2|"0,54.50,284.24,5632.45,2567.50,460,0,0,0,0,0,0"|37|783736.429|22443.23

此目标是能够根据第二个字段的利润百分比生成利润分配图。我们一直在迭代销售记录,并在应用程序逻辑中保持字段的运行记录,但我想知道sql guru是否知道如何在SQL中完全执行此操作。

1 个答案:

答案 0 :(得分:1)

我假设数据看起来像这样:

| 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 |

首先,我们找到哪个" bin"每笔交易都包含在:

select customer, sale, floor(margin_pct/5) as bin from sales

然后取出这些结果并将其汇总到每个客户的箱子中:

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

最后,获取这些结果并按客户汇总:

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

这给出了

| CUSTOMER |       BINNED_MARGINS |
|----------|----------------------|
|        1 | 100.95, 12.99, 10.12 |
|        2 |         94.99, 92.98 |

我们几乎在那里,但显然我们有一个大问题。除非您保证您的记录总是包含在每个垃圾箱中,否则您的结果将毫无意义。

不幸的是,MySQL并没有为此提供优雅的解决方案。您最好的选择是make a range table加入。简单地:

| BIN |
|-----|
|   0 |
|   1 |
|   2 |
|   3 |
|   4 |
|   5 |
|   6 |
|   7 |
|   8 |
|   9 |

最后,通过加入bincustomer表,我们可以强制所有分档的值:

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

产地:

| 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