我从第三方收集了一些数据,其中一列是姓和名的串联-但两者之间没有空格。我的目标是在第二个大写字母之前插入一个空格,例如:
some_name
-------------
AdamPeterson
JohnSmith
StevenMulroy
将成为:
some_name
-------------
Adam Peterson
John Smith
Steven Mulroy
我知道这不是万无一失的,但这是我拥有的源数据所能获得的最好的结果。
我需要使用SQL而不是Excel等来执行此操作-因为数据会在数据库级别定期刷新,然后由另一个系统处理,而无需首先导出。
非常感谢您的帮助!
答案 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
?
当LIMIT
与LIMIT 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