如何在MySQL的字符串的第二个大写字母前插入空格?

时间:2019-02-05 17:57:09

标签: mysql sql

我从第三方收集了一些数据,其中一列是姓和名的串联-但两者之间没有空格。我的目标是在第二个大写字母之前插入一个空格,例如:

some_name
-------------
AdamPeterson
JohnSmith
StevenMulroy

将成为:

some_name
-------------
Adam Peterson
John Smith
Steven Mulroy

我知道这不是万无一失的,但这是我拥有的源数据所能获得的最好的结果。

我需要使用SQL而不是Excel等来执行此操作-因为数据会在数据库级别定期刷新,然后由另一个系统处理,而无需首先导出。

非常感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

对于Mysql 8

SELECT REGEXP_REPLACE(CAST('JohnLexxxanon' as BINARY), '^([A-Z][a-z]+)([A-Z][a-z]+)$', '$1 $2');

对于MariaDb 10 +

SELECT REGEXP_REPLACE(CAST('JohnLexxxanon' as BINARY), '^([A-Z][a-z]+)([A-Z][a-z]+)$', '\\1 \\2');

数据被强制转换为二进制以实现区分大小写。

这适用于MySql 8和MariaDb 10 +

答案 1 :(得分:2)

这里是所有MySQL 5.1+版本的常规查询,可以肯定它也将在MariaDB上运行。
总体思路是使用MySQL数字生成器将字符串拆分为“令牌”,并检查“ ASCII”范围(如果“令牌”是否为大写字母

查询

SELECT 
   names.name   
 ,  INSERT (
       names.name 
     , LOCATE(
           SUBSTRING(names.name, number_generator.number, 1)  
         , names.name   
       )
     , 1
     , CONCAT(' ', SUBSTRING(names.name, number_generator.number, 1))
   ) AS changed_name
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
) row1
  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
) row2
CROSS JOIN (
  SELECT @row := 0 
) init_user_params 
) AS number_generator
CROSS JOIN 
 names 
WHERE
   number_generator.number > 1
 AND
   ASCII(SUBSTRING(names.name, number_generator.number, 1)) BETWEEN 65 AND 90

结果

| name         | changed_name  |
| ------------ | ------------- |
| AdamPeterson | Adam Peterson |
| JohnSmith    | John Smith    |
| StevenMulroy | Steven Mulroy |

请参阅demo

注意

该查询在具有数百万甚至数十亿条记录的(非常)大型表上无法很好地扩展,因为CROSS JOIN

或者您可以通过

使用无表方法

CROSS JOIN ( SELECT 'AdamPeterson' AS name UNION SELECT 'JohnSmith' UNION SELECT 'StevenMulroy' ) AS names

看到demo

或者在有大桌子时使用批处理

CROSS JOIN ( SELECT name FROM names WHERE id >= 1 AND id <= 2 ORDER BY names.id ASC
) AS names

为什么没有LIMIT? 当LIMITLIMIT 1000000, 1000之类的大偏移量一起使用时,速度很慢。 MySQL需要从(在最坏的情况下为磁盘)临时表中提取1001000条记录并再次删除1000000条记录

看到demo

已编辑

  

在我看来,这一切都像是黑魔法!几乎完美-尝试   名称为“ AlexLafferty”或“ LaurenAnderson”。也许是一个单一的错误或   在A上有东西吗?感谢您的所有帮助!

经过审查,我发现在LOCATE(..)中使用INSERT(..)几乎是多余的,可以删除使其正常工作。

所以补丁是

SELECT 
    names.name   
 ,  INSERT (
       names.name 
     , number_generator.number
     , 1
     , CONCAT(' ', SUBSTRING(names.name, number_generator.number, 1))
   ) AS changed_name

请参阅demo