【问题标题】:MYSQL SUBSTRING_INDEX to extract each different string of a columnMYSQL SUBSTRING_INDEX 提取列的每个不同字符串
【发布时间】:2016-04-07 07:00:27
【问题描述】:

我试图在 MYSQL 的分隔符之间获取每个不同的字符串值。我尝试使用函数 SUBSTRING_INDEX,它适用于第一个字符串和第一个字符串的延续,但不适用于第二个字符串。这就是我的意思:

Table x                    The result

SELECT SUBSTRING_INDEX(path, ':', 2) as p, sum(count) as N From x Group by p UNION
SELECT SUBSTRING_INDEX(path, ':', 3) as p, sum(count) From x Group by p UNION
SELECT SUBSTRING_INDEX(path, ':', 4) as p, sum(count) From x Group by p UNION
SELECT SUBSTRING_INDEX(path, ':', 5) as p, sum(count) From x Group by p UNION
SELECT SUBSTRING_INDEX(path, ':', 6) as p, sum(count) From x Group by p;

我尝试在查询中添加SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(path, ':', 2), ':', 2) as p, sum(count) From x Group by p UNION SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(path, ':', 4), ':', 2) as p, sum(count) From x Group by p,但结果还是一样。我想要做的不仅是获得字符串 A1、A2、A3 组合的结果,还获得带有 B2、C2、D2 的字符串作为第一个提取的字符串,如下表所示:

+---------------+----+
|   p           |  N |
+---------------+----+
| :A1           | 4  |
| ...           | ...|
| :B1           | 3  |
| :B1:C2        | 2  |
|...            | ...|
+---------------+----+

获得这样的结果的正确函数是什么?任何帮助表示赞赏,谢谢。

【问题讨论】:

  • 没有以 :B1 开头的路径,你能澄清一下这个输出吗
  • @RyanVincent 会检查它。
  • @RichardSt-Cyr 不,我不是这个意思。
  • @amdixon 是的,没有以 B1 开头的路径。但我想要输出变化。例如路径 :A1:B2:C3:D4:G5 -> :A1, :A1:B2, .., :B2, B2:C3 等

标签: mysql split substring


【解决方案1】:

假设路径上的所有字符串节点都是两个字符长并且所有路径的长度都相同..

计划

  • 使用每个块的固定长度 2 创建从路径的某个开始到结束的有效子字符串序列。..
  • 在上面加入自身以获取不到达路径末尾的路径
  • 使用上面计算的子字符串索引在 x.path 上获取子字符串
  • 在 x.path 子序列上聚合总和

设置

create table x
(
  path varchar(23) primary key not null,
  count integer not null
);

insert into x
( path, count )
values
( ':A1:B2:C1:D1:G1' , 3 ),
( ':A1:B2:C1:D1:G4' , 1 ),
( ':A2:B1:C2:D2:G4' , 2 )
;

drop view if exists digits_v;
create view digits_v
as
select 0 as n
union all
select 1 union all select 2 union all select 3 union all 
select 4 union all select 5 union all select 6 union all
select 7 union all select 8 union all select 9
;

查询

select substring(x.path, `start`, `len`) as chunk, sum(x.count)
from x
cross join
(
  select o1.`start`, o2.`len`
  from
  (
    select 1 + 3 * seq.n as `start`, 15 - 3 * seq.n as `len`
    from digits_v seq
    where 1 + 3 * seq.n between 1 and 15
    and   15 - 3 * seq.n  between 1 and 15
  ) o1
  inner join
  (
    select 1 + 3 * seq.n as `start`, 15 - 3 * seq.n as `len`
    from digits_v seq
    where 1 + 3 * seq.n between 1 and 15
    and   15 - 3 * seq.n  between 1 and 15
  ) o2
  on  o2.`start` >= o1.`start` 
) splices
where substring(x.path, `start`, `len`) <> ''
group by substring(x.path, `start`, `len`)
order by length(substring(x.path, `start`, `len`)), substring(x.path, `start`, `len`)
;

输出

+-----------------+--------------+
|      chunk      | sum(x.count) |
+-----------------+--------------+
| :A1             |            4 |
| :A2             |            3 |
| :A3             |            3 |
| ...             |          ... |
| :A1:B2          |            4 |
| :A2:B1          |            3 |
| :A3:B3          |            2 |
| :A3:B4          |            1 |
| ...             |          ... |
| :A1:B2:C1       |            4 |
| :A2:B1:C2       |            2 |
| :A2:B1:D2       |            3 |
| :A3:B3:C4       |            2 |
| :A3:B4:C2       |            1 |
| ...             |          ... |
| :A1:B2:C1:D1    |            4 |
| :A2:B1:C2:D2    |            2 |
| :A3:B3:C4:D3    |            2 |
| :A3:B4:C2:D3    |            1 |
| ...             |          ... |
| :A1:B2:C1:D1:G1 |            3 |
| :A1:B2:C1:D1:G4 |            1 |
| :A2:B1:C2:D2:G4 |            2 |
| :A3:B3:C4:D3:G7 |            2 |
| :A3:B4:C2:D3:G7 |            1 |
+-----------------+--------------+

sqlfiddle

【讨论】:

  • 是的,输出正是我所需要的。太感谢了!我将了解您的查询以了解这些功能。
  • 主要是了解序列生成器和有效子字符串(来自固定长度的 2 个节点)。如果节点变得可变长度,复杂性将增加更多;)
猜你喜欢
  • 1970-01-01
  • 2019-02-17
  • 1970-01-01
  • 2012-04-06
  • 2015-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-08
相关资源
最近更新 更多