mysql pivot-like操作,用于获取每种事件类型每天总事件百分比的细分

yshpjwxd  于 2021-07-26  发布在  Java
关注(0)|答案(1)|浏览(310)

有一张事件表

  1. created_at DATETIME
  2. event_type STRING
  3. # Some other columns with data about the event

我想做的是能够得到每天事件总数的百分比 event_type .
因此,我将事件分组,以获得每个事件每天的计数:

  1. # Lazily used date_bucket in GROUP BY since it's valid MySQL.
  2. # Is that bad since it's not standard SQL?
  3. #
  4. SELECT
  5. DATE(created_at) as date_bucket,
  6. event_type,
  7. COUNT(*) as number
  8. FROM
  9. example_table
  10. GROUP BY
  11. date_bucket, event_type

如果我们吵架了

  1. # Columns (date_bucket, event_type, number)
  2. #
  3. ('2020-06-02', 'exampleG1', 5)
  4. ('2020-06-02', 'exampleG2', 10)
  5. ('2020-06-02', 'exampleG3', 20)
  6. ('2020-06-03', 'exampleG1', 10)

我希望能够得到一些同等的处理

  1. # Columns (date_bucket, exampleG1, exampleG2, exampleG3)
  2. #
  3. ('2020-06-02', 15/35, 10/35, 20/35)
  4. ('2020-06-03', 10/10, 0, 0)

我不知道有什么区别 event_type 之前的值,而不是所有的组值可能在所有日期都存在,在这种情况下,该类型的值在该日期应为0。
我想做一些pivot操作,但是mysql似乎不支持pivots,所以我有点不知道如何处理这个问题。
如果我提前知道有效事件类型的集合,我想我可以对可能的类型进行一些讨厌的详细查询,但是集合是可变的。
有没有一个优雅的方法来实现这一点?

93ze6v8z

93ze6v8z1#

我不知道不同的事件类型值
您要求的是动态sql。也就是说,从另一个列出不同查询的查询动态构建查询字符串 event_type 值,然后执行它。在mysql中,这是使用准备好的语句实现的。
以下是操作方法:

  1. select @sql := group_concat(distinct
  2. 'sum(case when event_type = ''',
  3. event_type, ''' then number else 0 end)/sum(number) as `ratio_',
  4. event_type, '`'
  5. )
  6. from example_table;
  7. set @sql = concat(
  8. 'select date(created_at) date_bucket, ',
  9. @sql,
  10. ' from example_table group by date(created_at) order by date_bucket'
  11. );
  12. -- debug
  13. select @sql;
  14. -- execute
  15. prepare stmt from @sql;
  16. execute stmt;
  17. deallocate prepare stmt;

对于示例数据,这将生成以下查询:

  1. select
  2. date(created_at) date_bucket,
  3. sum(case when event_type = 'exampleG1' then number else 0 end)/sum(number) as `ratio_exampleG1`,
  4. sum(case when event_type = 'exampleG2' then number else 0 end)/sum(number) as `ratio_exampleG2`,
  5. sum(case when event_type = 'exampleG3' then number else 0 end)/sum(number) as `ratio_exampleG3`
  6. from example_table
  7. group by date(created_at)
  8. order by date_bucket

结果如下:

  1. date_bucket | ratio_exampleG1 | ratio_exampleG2 | ratio_exampleG3
  2. :---------- | --------------: | --------------: | --------------:
  3. 2020-06-02 | 0.1429 | 0.2857 | 0.5714
  4. 2020-06-03 | 1.0000 | 0.0000 | 0.0000

db小提琴演示

展开查看全部

相关问题