【问题标题】:mysql select substrings and group them by columnmysql选择子字符串并按列分组
【发布时间】:2014-02-07 21:56:49
【问题描述】:

我正在尝试将我的 MySQL 数据库上的表中的数据分成一个。

列包含如下数据:

de:"Sweatjacke*";en:"jacket*";pl:"bluza*";
de:"*";en:"*";pl:"bluza*";
fr:"*";de:"*";en:"*";pl:"dres junior*";cz:"*";
pl:"bluza";

我正在尝试将所有翻译分成单独的列。已经提供了解决方案来做到这一点:

SELECT 
SUBSTRING_INDEX(SUBSTRING_INDEX(name, ';', 1), ';', -1) as tr1,
SUBSTRING_INDEX(SUBSTRING_INDEX(name, ';', 2), ';', -1) as tr2,
SUBSTRING_INDEX(SUBSTRING_INDEX(name, ';', 3), ';', -1) as tr3,
SUBSTRING_INDEX(SUBSTRING_INDEX(name, ';', 4), ';', -1) as tr4,
SUBSTRING_INDEX(SUBSTRING_INDEX(name, ';', 5), ';', -1) as tr5
FROM  product;

声明,但结果是:

tr1     tr2     tr3     tr4     tr5
fr:"*"  de:"*"  en:"*"  pl:"bluza*" cz:"*"
fr:"*"  de:"Sweatjacke*"    en:"jacket*"    pl:"bluza*" cz:"*"
de:"Sweatjacke*"    en:"jacket*"    pl:"bluza*" 

我想让结果按翻译类型 (pl/de/en) 进行分类,因此在每个列中都存在一种类型的翻译。例如在 column1 = pl:, column2 = en:

有没有人遇到过类似的问题并且知道解决方法?

【问题讨论】:

  • 这样做的困难是为什么你不应该使用这种桌子设计。您需要了解数据库规范化。
  • 告诉那个创造这个桌子设计的人 ;-) 我是那个试图修复它的人。
  • 我认为,如果您在 Internet 上搜索,您可以找到一些使用 regexp 进行子字符串提取的 UDF。使用普通的 MySQL 函数没有简单的方法。
  • SELECT SUBSTRING_INDEX(SUBSTRING(name, LOCATE("pl:", name), 150), ';', 1) AS pl, SUBSTRING_INDEX(SUBSTRING(name, LOCATE("en:", name ) , 150 ) , ';', 1 ) AS en, SUBSTRING_INDEX( SUBSTRING( name, LOCATE( "de:", name ) , 150 ) , ';', 1 ) AS de, SUBSTRING_INDEX( SUBSTRING( name, LOCATE ( "fr:", name ) , 150 ) , ';', 1 ) AS fr FROM product 完成了这项工作 ;-) 谢谢!

标签: mysql sql database substring


【解决方案1】:

据我了解,您希望 UNPIVOT 您的数据。 MySQL 中没有这样的功能,所以您可能希望将数据导出到 MSSQL(您可以使用免费的 MSSQL Express)并使用 UNPIVOT 功能:http://technet.microsoft.com/en-us/library/ms177410(v=sql.105).aspx

【讨论】:

  • Thx IgorM,但它与旋转/取消旋转无关。我想拆分列。但不仅要使用';'来拆分它分隔符,但也将数据分配到正确的列中。
【解决方案2】:

您需要取消透视数据,然后选择每个值的第一部分和第二部分,然后重新聚合它。

但是,更好的数据形式实际上是具有语言/翻译。以下产生:

select substring_index(tr, ':', 1) as l, substring_index(tr, ':', 2) as t, name
from (select SUBSTRING_INDEX(SUBSTRING_INDEX(name, ';', n.n), ';', -1) as tr, n, name
      from product p cross join
           (select 1 as n union all select 2 union all select 3 union all select 4 union all
            select 5
           ) n
     ) n

您可能需要一个“id”列或“word”列来标识每一行,而不是 name 列。

您现在可以旋转该结果以获得您想要的结果:

select max(case when l = 'en' then name end) as en,
       max(case when l = 'fr' then name end) as fr,
       max(case when l = 'de' then name end) as de,
       max(case when l = 'pl' then name end) as pl,
       max(case when l = 'cz' then name end) as cz
from (select substring_index(tr, ':', 1) as l, substring_index(tr, ':', 2) as t, name
      from (select SUBSTRING_INDEX(SUBSTRING_INDEX(name, ';', n.n), ';', -1) as tr, n, name
            from product p cross join
                 (select 1 as n union all select 2 union all select 3 union all select 4 union all
                  select 5
                 ) n
           ) n
      ) lt
group by name;

【讨论】:

  • 谢谢戈登,但事实并非如此。设法使用子字符串解决它:
【解决方案3】:

设法通过使用一些与字符串相关的函数来解决它:

SELECT 
SUBSTRING_INDEX( SUBSTRING( name, LOCATE( "pl:", name ) , 150 ) , ';', 1 ) AS pl,
SUBSTRING_INDEX( SUBSTRING( name, LOCATE( "en:", name ) , 150 ) , ';', 1 ) AS en, 
SUBSTRING_INDEX( SUBSTRING( name, LOCATE( "de:", name ) , 150 ) , ';', 1 ) AS de, 
SUBSTRING_INDEX( SUBSTRING( name, LOCATE( "fr:", name ) , 150 ) , ';', 1 ) AS fr
FROM product

感谢大家的帮助。

【讨论】:

  • 只要您可以对查询中的语言列表进行硬编码,此方法就可以工作。
猜你喜欢
  • 2013-05-21
  • 2018-04-05
  • 2018-09-07
  • 2017-06-17
  • 2018-08-06
  • 2015-08-29
  • 2021-08-04
  • 2014-01-10
  • 2017-01-08
相关资源
最近更新 更多