将带有“+”分隔符的字符串拆分为单独的行并应用聚合

Posted

技术标签:

【中文标题】将带有“+”分隔符的字符串拆分为单独的行并应用聚合【英文标题】:Splitting string with '+' seperator into seperate rows and apply aggregation 【发布时间】:2019-03-21 00:59:11 【问题描述】:

数据不是静态的,由 + 分隔的字符组可能会有所不同。我希望所有由 + 分隔的字符都按行排列,然后在其顶部应用聚合。我在 Windows 中使用 mysql 5.7.14。 假设数据是:

group   val
a+b     10
a       5
b       6
b+d+c   12
d       13
c+d     12

输出应该是这样的:

grp_item val
a        15
b        28
c        24
d        24   

【问题讨论】:

这是一个非常糟糕的设计。考虑规范化您的表格。 这不是表格,而是算法的输出 那你可以看一下算法逻辑,以更简单的方式给出输出。处理您当前的输入将涉及大量字符串操作,这将非常冗长且效率低下。 这就是我从客户那里获取数据的方式。我无法控制 那么我建议你在应用程序代码中进行这些操作(例如:php、Java、C、C++、Python 等) 【参考方案1】:

就像我说的 MySQL 查询很复杂.. 一般的想法是一个 MySQL 数字生成器,它生成 1 到 10000,因此它支持 10000 个分隔值,组列中带有 + 号。 + 号之间的数据无关紧要。

查询

SELECT 
   Table1_unique_groups.`group`
 , SUM(Table1.val)
FROM (

SELECT 
 DISTINCT
   SUBSTRING_INDEX(SUBSTRING_INDEX(Table1.`group`, '+', number_generator.number), '+', -1) AS `group`

FROM (
  SELECT 
   @row := @row + 1 AS number
  FROM (
    SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
  ) record_1
  CROSS JOIN (
    SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
  ) record_2    
  CROSS JOIN (
    SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
  ) record_4
  CROSS JOIN (
    SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
  ) record_5     
  CROSS JOIN (
    SELECT @row := 0 
  ) AS init_user_params
) AS number_generator
CROSS JOIN 
 Table1 

) AS Table1_unique_groups

INNER JOIN 
  Table1
ON
  FIND_IN_SET(Table1_unique_groups.`group`, REPLACE(Table1.group, '+', ','))

GROUP BY 
 Table1_unique_groups.`group`

结果

| group | SUM(Table1.val) |
| ----- | --------------- |
| a     | 15              |
| b     | 28              |
| c     | 24              |
| d     | 37              |

DB Fiddle demo

【讨论】:

我认为 UNION 可以用 UNION ALL 代替 - 将使查询效率略微提高 “我认为 UNION 可以用 UNION ALL 代替 - 将使查询稍微更有效” 这真的没那么重要,MySQL 优化器没有告诉你的是,有或没有 UNION 总是需要一个临时表来执行我的@MadhurBhaiya post of mine dba.stackexchange.com/a/54184/27070 off C/C++ 源代码分析 MySQL 的 union 部分。

以上是关于将带有“+”分隔符的字符串拆分为单独的行并应用聚合的主要内容,如果未能解决你的问题,请参考以下文章

将逗号分隔的单元格拆分为多行,保持原始行不变?

将嵌入的 CSV 文本拆分为单独的行

将逗号分隔的字符串拆分为mysql中的行

MySQL查询将分隔字符串值拆分为单独的列[重复]

将数据框转换为另一个数据框,将复合字符串单元格拆分为单独的行[重复]

将逗号分隔的字符串转换为单独的行