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

标签 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”将根据 5 pct 增量的“bins”生成包含客户聚合的数组或 csv_list。此列的输出将包含 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 大师知道如何完全在 SQL 中执行此操作。

最佳答案

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

| 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 表,我们可以强制所有 bin 的值:

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

关于Mysql 查询生成 'bin' ed 总和以及一组查询中的其他聚合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22414336/

相关文章:

java - 用 JPA 创建数据库?

mysql - MYSQL 中最常见名字的更快排名

ruby-on-rails - 不在 Heroku 上工作的 RoR Postgresql 时区组

python - 在pandas中groupby之后过滤数据框

MySQL 按不同的列组合进行分组

sql - 获取 SQL 查询中每个不同记录的最大平均值

MYSQL : Error in Tigger

MYSQL CSV导入字符变成 '?'

sql - 连接更多表时聚合函数返回错误值

mysql - 如何折叠日期/时间范围内的相同行?