【问题标题】:How do I pull out specific strings from a comma separated string?如何从逗号分隔的字符串中提取特定字符串?
【发布时间】:2022-01-19 03:23:42
【问题描述】:

我有一个这样的字符串;

"field1=lance,field2=peter,field3=john"

实际字符串有20+个字段,我想按名称拉出具体值。

例如,我想提取“field2”的值并返回值“peter”,

谁能给我一个优雅的方式在 MySQL 中执行此操作?

我应该提到,这是来自电子商务系统的标准字段格式。我无法控制格式。可以通过 API 干净地提取数据,但这将是一项重要的额外工作,尤其是因为我已经拥有这种格式的数据。

【问题讨论】:

  • 您真的不应该将数据存储在这样的关系数据库中,因为 1)这违反了关系数据库原则 2)mysql 具有一组有限的文本操作功能。如果您绝对必须在一个列中存储多个数据点,请使用 json 或 xml 格式,因为它们在 mysql 中具有支持。不支持您的格式。您必须自己解析字符串,没有任何解决方案是优雅的。如果您将字符串提取到具有更好字符串操作能力的外部程序,您可能会做得更好。
  • “优雅”的方式是规范化数据并将每个原子值存储在自己的行中,这是关系数据库[旨在]如何工作的本质。即使是 EAV 模型也会更可取。您可以考虑将数据转换为 json 数组并使用可用的内置方法。
  • SUBSTRING_INDEX(SUBSTRING_INDEX(column, 'field2=', -1), ',', 1)。并根据 WHERE。

标签: mysql sql


【解决方案1】:

有趣的问题。下面有很多,所以让我们分解一下。我们本质上是构建一个查询并执行 stmt

DELIMITER $$

DROP PROCEDURE IF EXISTS proc_loop_test$$
CREATE PROCEDURE proc_loop_test()

#create empty query string
set @sqlstring = '';

#set your string of fields, not sure where this comes from
set @mystring = 'field1=lance,field2=peter,field3=john';

#create number of times we will loop through the string
set @num = (select length(@mystring)
- length(replace('field1=lance,field2=peter,field3=john',',','')) +1);

#init loop
loop LOOP
#create a short string just taking the "last" field/value pair
set @shtstring = (select SUBSTRING_INDEX(@mystring,',',-1));

#recreate your query string removing the substring we created
set @mystring = (select left(replace(@mystring,@shtstring,''),length(replace(@mystring,@shtstring,''))-1));

#add to your query string, we will build this for each 
set @sqlstring = concat(@sqlstring ,(select 
concat('''',SUBSTRING_INDEX(@shtstring,'=',-1),'''' 
,' as ', 
left(@shtstring,(position('=' in @shtstring) -1))) ),',');
#reduce our count by one as we have removed the latest field
set @num = @num - 1;

#leave the loop when no fields left
if @num = 0 then leave LOOP;
end if;
end loop LOOP;

END$$

DELIMITER ;

#create a query statement to execute
set @query = (select concat('select ',left(@sqlstring, length(@sqlstring)-1)));

#execute the query!
PREPARE stmt FROM @query;
EXECUTE stmt;

结果

field3  field2  field1
john    peter   lance

没有数组逻辑,这在 presto SQL 等中会很简单。因为您可以随时定义任意数量的字段,我们将需要loop,不幸的是您不能循环进入mysql无需创建procedure

这是前几行。我们还根据您的源和迭代次数(字符串中的字段数)创建完整的字符串。

然后基本上我们迭代地隔离“最后一个”字段/值对,重新排列每一个,以便field1=john 变成更适合 sql 的 'john' as field',

每次循环时我们都会减少计数器和字符串,直到计数器为 0。此时我们停止。

然后我们 prepare 使用我们的值/字段对和“选择”字符串进行查询。然后execute 你得到你的值作为字段

信用 Dynamic Strings prepare/exec Looping and stored procs Simulating Split function

【讨论】:

    【解决方案2】:

    @Akina 评论中的这个答案非常有效。

    SUBSTRING_INDEX(SUBSTRING_INDEX(column, 'field2=', -1), ',', 1)
    

    相应地WHERE

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-28
      • 1970-01-01
      • 1970-01-01
      • 2012-05-19
      • 1970-01-01
      相关资源
      最近更新 更多